diff -u --recursive --new-file v2.4.0-test5/linux/CREDITS linux/CREDITS --- v2.4.0-test5/linux/CREDITS Thu Jul 27 17:37:59 2000 +++ linux/CREDITS Fri Aug 4 17:59:14 2000 @@ -1071,15 +1071,11 @@ D: Small/Industrial Driver Project N: Nick Holloway -E: Nick.Holloway@alfie.demon.co.uk -E: Nick.Holloway@parallax.co.uk -W: http://www.alfie.demon.co.uk/ -P: 1024/75C49395 3A F0 E3 4E B7 9F E0 7E 47 A3 B0 D5 68 6A C2 FB +E: Nick.Holloway@pyrites.org.uk +W: http://www.pyrites.org.uk/ +P: 1024/36115A04 F4E1 3384 FCFD C055 15D6 BA4C AB03 FBF8 3611 5A04 D: Occasional Linux hacker... -S: 15 Duke Street -S: Chapelfields -S: Coventry -S: CV5 8BZ +S: (ask for current address) S: United Kingdom N: Ron Holt @@ -1221,9 +1217,10 @@ S: USA N: Dave Jones +E: davej@suse.de E: dave@powertweak.com E: djones2@glam.ac.uk -W: http://linux.powertweak.com +W: http://powertweak.sourceforge.net D: Moved PCI bridge tuning to userspace (Powertweak). D: Centaur/IDT Winchip/Winchip 2 tweaks. D: AFFS fixes for 2.3.x @@ -1556,6 +1553,12 @@ S: Niwot, Colorado 80503 S: USA +N: Robert M. Love +E: rml@tech9.net +E: rml@ufl.edu +D: misc. kernel hacking and debugging +S: FL, USA + N: Martin von Löwis E: loewis@informatik.hu-berlin.de D: script binary format @@ -1812,6 +1815,10 @@ S: Reinholdstrasse 14 S: D-37083 Goettingen S: Germany + +N: Thomas Molina +E: tmolina@home.com +D: bug fixes, documentation, minor hackery N: David Mosberger-Tang E: davidm@hpl.hp.com if IA-64 related, else David.Mosberger@acm.org diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/Changes linux/Documentation/Changes --- v2.4.0-test5/linux/Documentation/Changes Thu Jul 27 17:37:59 2000 +++ linux/Documentation/Changes Fri Aug 4 11:23:37 2000 @@ -43,7 +43,7 @@ o Gnu C 2.7.2.3 # gcc --version o binutils 2.9.1.0.22 # ld -v o util-linux 2.10g # chsh -v -o modutils 2.3.10 # insmod -V +o modutils 2.3.13 # insmod -V o e2fsprogs 1.18 # /sbin/tune2fs --version o pcmcia-cs 3.1.13 # cardmgr -V o PPP 2.4.0b1 # pppd --version @@ -266,8 +266,8 @@ Modutils -------- -o ftp://ftp.kernel.org/pub/linux/utils/kernel/modutils/v2.3/modutils-2.3.9.tar.gz - +o ftp://ftp.kernel.org/pub/linux/utils/kernel/modutils/v2.3/modutils-2.3.13.tar.gz + E2fsprogs --------- diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.4.0-test5/linux/Documentation/Configure.help Thu Jul 27 17:37:59 2000 +++ linux/Documentation/Configure.help Wed Aug 9 13:49:28 2000 @@ -4649,9 +4649,11 @@ Kernel/User network link driver CONFIG_NETLINK This driver allows for two-way communication between the kernel and - user processes; the user processes communicate with the kernel by - reading from and writing to character special files in the /dev - directory having major mode 36. + user processes. It does so by creating a new socket family, PF_NETLINK. + Over this socket, the kernel can send and receive datagrams carrying + information. It is documented on many systems in netlink(7), a HOWTO is + provided as well, for example on + http://snafu.freedom.org/linux2.2/docs/netlink-HOWTO.html So far, the kernel uses this feature to publish some network related information if you say Y to "Routing messages", below. You also need @@ -4665,16 +4667,19 @@ Routing messages CONFIG_RTNETLINK - If you say Y here and create a character special file /dev/route - with major number 36 and minor number 0 using mknod ("man mknod"), - you (or some user space utility) can read some network related - routing information from that file. Everything you write to that - file will be discarded. + If you say Y here, userspace programs can receive some network + related routing information over the netlink. 'rtmon', supplied + with the iproute2 package (ftp://ftp.inr.ac.ru), can read and + interpret this data. Information sent to the kernel over this link + is ignored. Netlink device emulation CONFIG_NETLINK_DEV + This option will be removed soon. Any programs that want to use + character special nodes like /dev/tap0 or /dev/route (all with major + number 36) need this option, and need to be rewritten soon to use + the real netlink socket. This is a backward compatibility option, choose Y for now. - This option will be removed soon. Asynchronous Transfer Mode (ATM) CONFIG_ATM @@ -8915,8 +8920,15 @@ Enable Power Management (EXPERIMENTAL) CONFIG_EEPRO100_PM - If you want to play around with power management code - that has been reported to lock up some machines, say Y here. + Many Intel EtherExpress PRO/100 PCI network cards are capable + of providing power management capabilities. To make use of these + capabilities, say Y. + + WARNING: This option is intended for kernel developers and testers. + It is still very experimental, with some people reporting complete + lockups. + + It is recommended to say N here. ICL EtherTeam 16i/32 support (EXPERIMENTAL) CONFIG_ETH16I @@ -16440,6 +16452,19 @@ boards from BVM Ltd. Everyone using one of these boards should say Y here. +7-Segment Display support +CONFIG_DISPLAY7SEG + This is the driver for the 7-segment display and LED present on + Sun Microsystems CompactPCI models CP1400 and CP1500. + + This driver 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 display7seg.o. If you want to compile it + as a module, say M here and read Documentation/modules.txt. + + If you do not have a CompactPCI model CP1400 or CP1500, or + another UltraSPARC-IIi-cEngine boardset with a 7-segment display, + you should say N to this option. # # A couple of things I keep forgetting: diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/DMA-mapping.txt linux/Documentation/DMA-mapping.txt --- v2.4.0-test5/linux/Documentation/DMA-mapping.txt Wed Apr 26 16:34:06 2000 +++ linux/Documentation/DMA-mapping.txt Fri Jul 28 12:50:51 2000 @@ -111,7 +111,7 @@ - Consistent DMA mappings which are usually mapped at driver initialization, unmapped at the end and for which the hardware should - guarentee that the device and the cpu can access the data + guarantee that the device and the cpu can access the data in parallel and will see updates made by each other without any explicit software flushing. @@ -126,7 +126,7 @@ The invariant these examples all require is that any cpu store to memory is immediately visible to the device, and vice - versa. Consistent mappings guarentee this. + versa. Consistent mappings guarantee this. - Streaming DMA mappings which are usually mapped for one DMA transfer, unmapped right after it (unless you use pci_dma_sync below) and for which @@ -171,9 +171,9 @@ The cpu return address and the DMA bus master address are both guaranteed to be aligned to the smallest PAGE_SIZE order which is greater than or equal to the requested size. This invariant -exists (for example) to guarentee that if you allocate a chunk +exists (for example) to guarantee that if you allocate a chunk which is smaller than or equal to 64 kilobytes, the extent of the -buffer you receive will not cross a 64K boundry. +buffer you receive will not cross a 64K boundary. To unmap and free such a DMA region, you call: @@ -203,7 +203,7 @@ If you absolutely cannot know the direction of the DMA transfer, specify PCI_DMA_BIDIRECTIONAL. It means that the DMA can go in -either direction. The platform guarentees that you may legally +either direction. The platform guarantees that you may legally specify this, and that it will work, but this may be at the cost of performance for example. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/IO-mapping.txt linux/Documentation/IO-mapping.txt --- v2.4.0-test5/linux/Documentation/IO-mapping.txt Wed Jun 24 14:30:07 1998 +++ linux/Documentation/IO-mapping.txt Fri Jul 28 12:50:51 2000 @@ -176,7 +176,7 @@ didn't think straight when I wrote it originally. People who have to support both can do something like: - /* support old naming sillyness */ + /* support old naming silliness */ #if LINUX_VERSION_CODE < 0x020100 #define ioremap vremap #define iounmap vfree diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/README.DAC960 linux/Documentation/README.DAC960 --- v2.4.0-test5/linux/Documentation/README.DAC960 Tue Aug 31 17:29:12 1999 +++ linux/Documentation/README.DAC960 Fri Aug 4 13:11:00 2000 @@ -1,47 +1,52 @@ - Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux + Linux Driver for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers - Version 2.2.4 for Linux 2.2.11 - Version 2.0.4 for Linux 2.0.37 + Version 2.2.7 for Linux 2.2.16 + Version 2.4.7 for Linux 2.4.0 PRODUCTION RELEASE - 23 August 1999 + 1 August 2000 Leonard N. Zubkoff Dandelion Digital lnz@dandelion.com - Copyright 1998-1999 by Leonard N. Zubkoff + Copyright 1998-2000 by Leonard N. Zubkoff INTRODUCTION Mylex, Inc. designs and manufactures a variety of high performance PCI RAID controllers. Mylex Corporation is located at 34551 Ardenwood Blvd., Fremont, -California 94555, USA and can be reached at 510/796-6100 or on the World Wide -Web at http://www.mylex.com. Mylex RAID Technical Support can be reached by -electronic mail at support@mylex.com (for eXtremeRAID 1100 and older DAC960 -models) or techsup@mylex.com (for AcceleRAID models), by voice at 510/608-2400, -or by FAX at 510/745-7715. Contact information for offices in Europe and Japan -is available on the Web site. +California 94555, USA and can be reached at 510.796.6100 or on the World Wide +Web at http://www.mylex.com. Mylex Technical Support can be reached by +electronic mail at support@mylex.com, by voice at 510.608.2400, or by FAX at +510.745.7715. Contact information for offices in Europe and Japan is available +on their Web site. The latest information on Linux support for DAC960 PCI RAID Controllers, as well as the most recent release of this driver, will always be available from my Linux Home Page at URL "http://www.dandelion.com/Linux/". The Linux DAC960 -driver supports all current DAC960 PCI family controllers including the -AcceleRAID models, as well as the eXtremeRAID 1100; see below for a complete -list. For simplicity, in most places this documentation refers to DAC960 -generically rather than explicitly listing all the models. - -Bug reports should be sent via electronic mail to "lnz@dandelion.com". Please -include with the bug report the complete configuration messages reported by the -driver at startup, along with any subsequent system messages relevant to the -controller's operation, and a detailed description of your system's hardware -configuration. - -Please consult the DAC960 RAID controller documentation for detailed -information regarding installation and configuration of the controllers. This -document primarily provides information specific to the Linux DAC960 support. +driver supports all current Mylex PCI RAID controllers including the new +eXtremeRAID 2000/3000 and AcceleRAID 352/170 models which have an entirely new +firmware interface from the older eXtremeRAID 1100, AcceleRAID 150/200/250, and +DAC960PJ/PG/PU/PD/PL. See below for a complete controller list as well as +minimum firmware version requirements. For simplicity, in most places this +documentation refers to DAC960 generically rather than explicitly listing all +the supported models. + +Driver bug reports should be sent via electronic mail to "lnz@dandelion.com". +Please include with the bug report the complete configuration messages reported +by the driver at startup, along with any subsequent system messages relevant to +the controller's operation, and a detailed description of your system's +hardware configuration. Driver bugs are actually quite rare; if you encounter +problems with disks being marked offline, for example, please contact Mylex +Technical Support as the problem is related to the hardware configuration +rather than the Linux driver. + +Please consult the RAID controller documentation for detailed information +regarding installation and configuration of the controllers. This document +primarily provides information specific to the Linux support. DRIVER FEATURES @@ -60,16 +65,18 @@ from Linux while the system is operational. The DAC960 driver is architected to support up to 8 controllers per system. -Each DAC960 controller can support up to 15 disk drives per channel, for a -maximum of 45 drives on a three channel controller. The drives installed on a -controller are divided into one or more "Drive Groups", and then each Drive -Group is subdivided further into 1 to 32 "Logical Drives". Each Logical Drive -has a specific RAID Level and caching policy associated with it, and it appears -to Linux as a single block device. Logical Drives are further subdivided into -up to 7 partitions through the normal Linux and PC disk partitioning schemes. -Logical Drives are also known as "System Drives", and Drive Groups are also -called "Packs". Both terms are in use in the Mylex documentation; I have -chosen to standardize on the more generic "Logical Drive" and "Drive Group". +Each DAC960 parallel SCSI controller can support up to 15 disk drives per +channel, for a maximum of 60 drives on a four channel controller; the fibre +channel eXtremeRAID 3000 controller supports up to 125 disk drives per loop for +a total of 250 drives. The drives installed on a controller are divided into +one or more "Drive Groups", and then each Drive Group is subdivided further +into 1 to 32 "Logical Drives". Each Logical Drive has a specific RAID Level +and caching policy associated with it, and it appears to Linux as a single +block device. Logical Drives are further subdivided into up to 7 partitions +through the normal Linux and PC disk partitioning schemes. Logical Drives are +also known as "System Drives", and Drive Groups are also called "Packs". Both +terms are in use in the Mylex documentation; I have chosen to standardize on +the more generic "Logical Drive" and "Drive Group". DAC960 RAID disk devices are named in the style of the Device File System (DEVFS). The device corresponding to Logical Drive D on Controller C is @@ -82,17 +89,41 @@ Drive and 3 bits for the partition. - SUPPORTED DAC960/DAC1100 PCI RAID CONTROLLERS + SUPPORTED DAC960/AcceleRAID/eXtremeRAID PCI RAID CONTROLLERS -The following list comprises the supported DAC960 and DAC1100 PCI RAID -Controllers as of the date of this document. It is recommended that anyone -purchasing a Mylex PCI RAID Controller not in the following table contact the -author beforehand to verify that it is or will be supported. +The following list comprises the supported DAC960, AcceleRAID, and eXtremeRAID +PCI RAID Controllers as of the date of this document. It is recommended that +anyone purchasing a Mylex PCI RAID Controller not in the following table +contact the author beforehand to verify that it is or will be supported. + +eXtremeRAID 3000 + 1 Wide Ultra-2/LVD SCSI channel + 2 External Fibre FC-AL channels + 233MHz StrongARM SA 110 Processor + 64 Bit 33MHz PCI (backward compatible with 32 Bit PCI slots) + 32MB/64MB ECC SDRAM Memory + +eXtremeRAID 2000 + 4 Wide Ultra-160 LVD SCSI channels + 233MHz StrongARM SA 110 Processor + 64 Bit 33MHz PCI (backward compatible with 32 Bit PCI slots) + 32MB/64MB ECC SDRAM Memory + +AcceleRAID 352 + 2 Wide Ultra-160 LVD SCSI channels + 100MHz Intel i960RN RISC Processor + 64 Bit 33MHz PCI (backward compatible with 32 Bit PCI slots) + 32MB/64MB ECC SDRAM Memory + +AcceleRAID 170 + 1 Wide Ultra-160 LVD SCSI channel + 100MHz Intel i960RM RISC Processor + 16MB/32MB/64MB ECC SDRAM Memory eXtremeRAID 1100 (DAC1164P) 3 Wide Ultra-2/LVD SCSI channels 233MHz StrongARM SA 110 Processor - 64 Bit PCI (backward compatible with 32 Bit PCI slots) + 64 Bit 33MHz PCI (backward compatible with 32 Bit PCI slots) 16MB/32MB/64MB Parity SDRAM Memory with Battery Backup AcceleRAID 250 (DAC960PTL1) @@ -133,6 +164,9 @@ Intel i960 RISC Processor 2MB/4MB/8MB/16MB/32MB DRAM Memory +For the eXtremeRAID 2000/3000 and AcceleRAID 352/170, firmware version 6.00-01 +or above is required. + For the eXtremeRAID 1100, firmware version 5.06-0-52 or above is required. For the AcceleRAID 250, 200, and 150, firmware version 4.06-0-57 or above is @@ -163,13 +197,13 @@ DRIVER INSTALLATION -This distribution was prepared for Linux kernel version 2.2.11 or 2.0.37. +This distribution was prepared for Linux kernel version 2.2.16 or 2.4.0. To install the DAC960 RAID driver, you may use the following commands, replacing "/usr/src" with wherever you keep your Linux kernel source tree: cd /usr/src - tar -xvzf DAC960-2.2.4.tar.gz (or DAC960-2.0.4.tar.gz) + tar -xvzf DAC960-2.2.7.tar.gz (or DAC960-2.4.7.tar.gz) mv README.DAC960 linux/Documentation mv DAC960.[ch] linux/drivers/block patch -p0 < DAC960.patch @@ -201,13 +235,13 @@ drives using the BIOS Configuration Utility or DACCF. Please note that since there are only at most 6 usable partitions on each logical drive, systems requiring more partitions should subdivide a drive group into multiple logical -drives, each of which can have up to 6 partitions. Also, note that with large -disk arrays it is advisable to enable the 8GB BIOS Geometry (255/63) rather -than accepting the default 2GB BIOS Geometry (128/32); failing to so do will -cause the logical drive geometry to have more than 65535 cylinders which will -make it impossible for FDISK to be used properly. The 8GB BIOS Geometry can be -enabled by configuring the DAC960 BIOS, which is accessible via Alt-M during -the BIOS initialization sequence. +drives, each of which can have up to 6 usable partitions. Also, note that with +large disk arrays it is advisable to enable the 8GB BIOS Geometry (255/63) +rather than accepting the default 2GB BIOS Geometry (128/32); failing to so do +will cause the logical drive geometry to have more than 65535 cylinders which +will make it impossible for FDISK to be used properly. The 8GB BIOS Geometry +can be enabled by configuring the DAC960 BIOS, which is accessible via Alt-M +during the BIOS initialization sequence. For maximum performance and the most efficient E2FSCK performance, it is recommended that EXT2 file systems be built with a 4KB block size and 16 block diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/arm/SA1100/ThinClient linux/Documentation/arm/SA1100/ThinClient --- v2.4.0-test5/linux/Documentation/arm/SA1100/ThinClient Fri May 12 14:18:55 2000 +++ linux/Documentation/arm/SA1100/ThinClient Fri Jul 28 12:50:51 2000 @@ -10,7 +10,7 @@ . It's currently possible to mount a root filesystem via NFS providing a -complete Linux environment. Otherwyse a ramdisk image may be used. Use +complete Linux environment. Otherwise a ramdisk image may be used. Use 'make thinclient_config' before any 'make config'. This will set up defaults for ThinClient support. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/arm/empeg/ir.txt linux/Documentation/arm/empeg/ir.txt --- v2.4.0-test5/linux/Documentation/arm/empeg/ir.txt Fri Oct 22 13:21:43 1999 +++ linux/Documentation/arm/empeg/ir.txt Fri Jul 28 12:50:51 2000 @@ -17,7 +17,7 @@ Go low for less than 2T (Around 750us) Rather than repeat a signal when the button is held down certain buttons -generate the following code to indicate repitition. +generate the following code to indicate repetition. Go low for approx 16T Go high for approx 4T diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/arm/nwfpe/README linux/Documentation/arm/nwfpe/README --- v2.4.0-test5/linux/Documentation/arm/nwfpe/README Thu Feb 10 17:11:01 2000 +++ linux/Documentation/arm/nwfpe/README Fri Jul 28 12:50:51 2000 @@ -15,7 +15,7 @@ important. Another choice I made was in the file structure. I have attempted to -contain all operating system specfic code in one module (fpmodule.*). +contain all operating system specific code in one module (fpmodule.*). All the other files contain emulator specific code. This should allow others to port the emulator to NetBSD for instance relatively easily. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/cdrom/cdrom-standard.tex linux/Documentation/cdrom/cdrom-standard.tex --- v2.4.0-test5/linux/Documentation/cdrom/cdrom-standard.tex Sun Mar 21 18:37:56 1999 +++ linux/Documentation/cdrom/cdrom-standard.tex Fri Jul 28 12:50:51 2000 @@ -919,7 +919,7 @@ than fixing this interface by changing the assumptions it was made under, thereby breaking all user applications that use this function, the \UCD\ implements this $ioctl$ as follows: If the CD in - question has audio tracks on it, and it has absolutly no CD-I, XA, + question has audio tracks on it, and it has absolutely no CD-I, XA, or data tracks on it, it will be reported as $CDS_AUDIO$. If it has both audio and data tracks, it will return $CDS_MIXED$. If there are no audio tracks on the disc, and if the CD in question has any diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/cdrom/ide-cd linux/Documentation/cdrom/ide-cd --- v2.4.0-test5/linux/Documentation/cdrom/ide-cd Mon Jan 18 12:47:33 1999 +++ linux/Documentation/cdrom/ide-cd Fri Jul 28 12:50:51 2000 @@ -286,7 +286,7 @@ Unfortunately, these drives seem to become very confused when we perform the standard Linux ATA disk drive probe. If you own one of these drives, you can bypass the ATA probing which confuses these CDROM drives, by - adding `append="hdX=noprobe hdX=cdrom"' to your lilo.conf file and runing + adding `append="hdX=noprobe hdX=cdrom"' to your lilo.conf file and running lilo (again where X is the drive letter corresponding to where your drive is installed.) diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/computone.txt linux/Documentation/computone.txt --- v2.4.0-test5/linux/Documentation/computone.txt Wed Apr 26 16:34:06 2000 +++ linux/Documentation/computone.txt Fri Jul 28 12:50:51 2000 @@ -93,7 +93,7 @@ to update the character drivers' makefile and configuration file, and other kernel source files. A build script (ip2build) was included which applies the patches if needed, and build any utilities needed. -What you recieve may be a single patch file in conventional kernel +What you receive may be a single patch file in conventional kernel patch format build script. That form can also be applied by running patch -p1 < ThePatchFile. Otherwise run ip2build. @@ -191,7 +191,7 @@ Intelliport II installations using the PowerPort expansion module can use the custom speed setting to select the highest speeds: 153,600 bps, 230,400 bps, 307,200 bps, 460,800bps and 921,600 bps. The base for -custom baud rate configuration is fixed at 921,600 for cards/expantion +custom baud rate configuration is fixed at 921,600 for cards/expansion modules with ST654's and 115200 for those with Cirrus CD1400's. This corresponds to the maximum bit rates those chips are capable. For example if the baud base is 921600 and the baud divisor is 18 then @@ -220,13 +220,13 @@ 2.2.x kernels and available as a configuration option in 2.3.46 and higher. Devfs allows for the automatic creation and management of device names under control of the device drivers themselves. The Devfs namespace is -hierarchial and reduces the clutter present in the normal flat /dev +hierarchical and reduces the clutter present in the normal flat /dev namespace. Devfs names and conventional device names may be intermixed. A userspace daemon, devfsd, exists to allow for automatic creation and management of symbolic links from the devfs name space to the conventional names. More details on devfs can be found on the DEVFS home site at or in the file kernel -documenation files, .../linux/Documenation/filesystems/devfs/REAME. +documentation files, .../linux/Documentation/filesystems/devfs/REAME. If you are using devfs, existing devices are automatically created within the devfs name space. Normal devices will be ttf/0 - ttf/255 and callout diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/cpqarray.txt linux/Documentation/cpqarray.txt --- v2.4.0-test5/linux/Documentation/cpqarray.txt Fri Jun 23 21:55:06 2000 +++ linux/Documentation/cpqarray.txt Fri Jul 28 12:50:51 2000 @@ -1,4 +1,4 @@ -This driver is for Compaq's SMART2 Intellegent Disk Array Controllers. +This driver is for Compaq's SMART2 Intelligent Disk Array Controllers. Supported Cards: ---------------- diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/fb/aty128fb.txt linux/Documentation/fb/aty128fb.txt --- v2.4.0-test5/linux/Documentation/fb/aty128fb.txt Tue Jan 11 22:31:36 2000 +++ linux/Documentation/fb/aty128fb.txt Fri Jul 28 12:50:51 2000 @@ -66,7 +66,7 @@ There are known and unknown bugs, features and misfeatures. Currently there are following known bugs: + This driver is still experimental and is not finished. Too many - bugs/eratta to list here. + bugs/errata to list here. -- Brad Douglas diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/fb/matroxfb.txt linux/Documentation/fb/matroxfb.txt --- v2.4.0-test5/linux/Documentation/fb/matroxfb.txt Mon Jul 10 16:47:18 2000 +++ linux/Documentation/fb/matroxfb.txt Fri Jul 28 12:50:51 2000 @@ -193,7 +193,7 @@ XF86_FBDev. dfp - enables digital flat panel interface. This option is incompatible with secondary (TV) output - if DFP is active, TV output must be - inactive and vice versa. DFP always uses same timming as primary + inactive and vice versa. DFP always uses same timing as primary (monitor) output. vesa:X - selects startup videomode. X is number from 0 to 0x1FF, see table above for detailed explanation. Default is 640x480x8bpp if driver diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/fb/vesafb.txt linux/Documentation/fb/vesafb.txt --- v2.4.0-test5/linux/Documentation/fb/vesafb.txt Thu Apr 29 11:53:41 1999 +++ linux/Documentation/fb/vesafb.txt Fri Jul 28 12:50:51 2000 @@ -62,7 +62,7 @@ 16M | 0x312 0x315 0x318 0x31B To enable one of those modes you have to specify "vga=ask" in the -lilo.conf file and rerun LILO. Then you can type in the descired +lilo.conf file and rerun LILO. Then you can type in the desired mode at the "vga=ask" prompt. For example if you like to use 1024x768x256 colors you have to say "305" at this prompt. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/filesystems/Locking linux/Documentation/filesystems/Locking --- v2.4.0-test5/linux/Documentation/filesystems/Locking Fri Jul 14 12:12:04 2000 +++ linux/Documentation/filesystems/Locking Fri Jul 28 12:50:51 2000 @@ -137,7 +137,7 @@ may be called from the request handler (/dev/loop). ->sync_page() locking rules are not well-defined - usually it is called with lock on page, but that is not guaranteed. Considering the currently -existsing instances of this method ->sync_page() itself doesn't look +existing instances of this method ->sync_page() itself doesn't look well-defined... ->bmap() is currently used by legacy ioctl() (FIBMAP) provided by some filesystems and by the swapper. The latter will eventually go away. All diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/filesystems/affs.txt linux/Documentation/filesystems/affs.txt --- v2.4.0-test5/linux/Documentation/filesystems/affs.txt Sun Mar 21 07:11:36 1999 +++ linux/Documentation/filesystems/affs.txt Fri Jul 28 12:50:51 2000 @@ -158,7 +158,7 @@ have an Amiga harddisk connected to your PC, it will overwrite the bytes 0x00dc..0x00df of block 0 with garbage, thus invalidating the Rigid Disk Block. Sheer luck has it that this is an unused -area of the RDB, so only the checksum doesn's match anymore. +area of the RDB, so only the checksum doesn't match anymore. Linux will ignore this garbage and recognize the RDB anyway, but before you connect that drive to your Amiga again, you must restore or repair your RDB. So please do make a backup copy of it diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/filesystems/coda.txt linux/Documentation/filesystems/coda.txt --- v2.4.0-test5/linux/Documentation/filesystems/coda.txt Thu Apr 29 11:53:41 1999 +++ linux/Documentation/filesystems/coda.txt Fri Jul 28 12:50:51 2000 @@ -1531,7 +1531,7 @@ DDeessccrriippttiioonn Remove all entries in the cache lying in a directory - CodaFid, and all children of this directory. This call is issed when + CodaFid, and all children of this directory. This call is issued when Venus receives a callback on the directory. @@ -1630,7 +1630,7 @@ The following requirements should be accommodated: - 1. The message queueus should have open and close routines. On Unix + 1. The message queues should have open and close routines. On Unix the opening of the character devices are such routines. +o Before opening, no messages can be placed. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/filesystems/fat_cvf.txt linux/Documentation/filesystems/fat_cvf.txt --- v2.4.0-test5/linux/Documentation/filesystems/fat_cvf.txt Sun Feb 28 09:47:37 1999 +++ linux/Documentation/filesystems/fat_cvf.txt Fri Jul 28 12:50:51 2000 @@ -140,7 +140,7 @@ THE KIND OF CVF I SUPPORT". The function must maintain the module usage counters for safety, i.e. do MOD_INC_USE_COUNT at the beginning and MOD_DEC_USE_COUNT at the end. The function *must not* assume that - successful recongition would lead to a call of the mount_cvf function + successful recognition would lead to a call of the mount_cvf function later. - mount_cvf: A function that sets up some values or initializes something additional diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/filesystems/hpfs.txt linux/Documentation/filesystems/hpfs.txt --- v2.4.0-test5/linux/Documentation/filesystems/hpfs.txt Fri Jun 4 01:06:29 1999 +++ linux/Documentation/filesystems/hpfs.txt Fri Jul 28 12:50:51 2000 @@ -25,14 +25,14 @@ - there is a list of text extensions (I thing it's better to not convert text file than to damage binary file). If you want to change that list, change it in the source. Original readonly HPFS contained some strange - heuristic alghoritm that I removed. I thing it's danger to let the + heuristic algorithm that I removed. I thing it's danger to let the computer decide whether file is text or binary. For example, DJGPP binaries contain small text message at the beginning and they could be misidentified and damaged under some circumstances. check=none,normal,strict (default normal) Check level. Selecting none will cause only little speedup and big danger. I tried to write it so that it won't crash if check=normal on - corrupted filesystems. check=strict means many superflous checks - + corrupted filesystems. check=strict means many superfluous checks - used for debugging (for example it checks if file is allocated in bitmaps when accessing it). errors=continue,remount-ro,panic (default remount-ro) @@ -65,12 +65,12 @@ Extended attributes -On HPFS partion, OS/2 can associate to each file a special information called +On HPFS partitions, OS/2 can associate to each file a special information called extended attributes. Extended attributes are pairs of (key,value) where key is an ascii string identifying that attribute and value is any string of bytes of variable length. OS/2 stores window and icon positions and file types there. So why not use it for unix-specific info like file owner or access rights? This -driver can do it. If you chown/chgrp/chmod on a hpfs partion, extended +driver can do it. If you chown/chgrp/chmod on a hpfs partition, extended attributes with keys "UID", "GID" or "MODE" and 2-byte values are created. Only that extended attributes those value differs from defaults specified in mount options are created. Once created, the extended attributes are never deleted, @@ -89,7 +89,7 @@ Symlinks -You can do symlinks on HPFS partion, symlinks are achieved by setting extended +You can do symlinks on HPFS partition, symlinks are achieved by setting extended attribute named "SYMLINK" with symlink value. Like on ext2, you can chown and chgrp symlinks but I don't know what is it good for. chmoding symlink results in chmoding file where symlink points. These symlinks are just for Linux use and @@ -107,12 +107,12 @@ America where people don't care much about codepages and so multiple codepages support is quite buggy. I have Czech OS/2 working in codepage 852 on my disk. Once I booted English OS/2 working in cp 850 and I created a file on my 852 -partion. It marked file name codepage as 850 - good. But when I again booted +partition. It marked file name codepage as 850 - good. But when I again booted Czech OS/2, the file was completely inaccessible under any name. It seems that OS/2 uppercases the search pattern with it's system code page (852) and file name it's comparing to with its code page (850). These could never match. Is it -really what IBM developers wanted? But problems countinue. When I created in -Czech OS/2 another file in that direcotry, that file was inaccesible too. OS/2 +really what IBM developers wanted? But problems continued. When I created in +Czech OS/2 another file in that directory, that file was inaccessible too. OS/2 probably uses different uppercasing method when searching where to place a file (note, that files in HPFS directory must be sorted) and when searching for a file. Finally when I opened this directory in PmShell, PmShell crashed (the @@ -199,7 +199,7 @@ marks them as short (and writes "minor fs error corrected"). This bug is not in HPFS386. -Codepage bugs decsribed above. +Codepage bugs described above. If you don't install fixpacks, there are many, many more... @@ -266,7 +266,7 @@ 1.99 Corrected a possible problem when there's not enough space while deleting file Now it tries to truncate the file if there's not enough space when deleting - Removed a lot of redundat code + Removed a lot of redundant code 2.00 Fixed a bug in rename (it was there since 1.96) Better anti-fragmentation strategy diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/filesystems/proc.txt linux/Documentation/filesystems/proc.txt --- v2.4.0-test5/linux/Documentation/filesystems/proc.txt Sun Nov 7 16:37:33 1999 +++ linux/Documentation/filesystems/proc.txt Fri Jul 28 12:50:51 2000 @@ -1047,7 +1047,7 @@ On a low-memory, single CPU system, you can safely set these values to 0 so you don't waste memory. It is used on SMP systems so that the system can -perform fast pagetable allocations without having to aquire the kernel memory +perform fast pagetable allocations without having to acquire the kernel memory lock. For large systems, the settings are probably fine. For normal systems they diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/filesystems/ufs.txt linux/Documentation/filesystems/ufs.txt --- v2.4.0-test5/linux/Documentation/filesystems/ufs.txt Tue Jun 29 09:12:32 1999 +++ linux/Documentation/filesystems/ufs.txt Fri Jul 28 12:50:51 2000 @@ -9,7 +9,7 @@ ufstype=type_of_ufs UFS is a file system widely used in different operating systems. - The problem are differencies among implementations. Features of + The problem are differences among implementations. Features of some implementations are undocumented, so its hard to recognize type of ufs automatically. That's why user must specify type of ufs manually by mount option ufstype. Possible values are: diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/filesystems/vfs.txt linux/Documentation/filesystems/vfs.txt --- v2.4.0-test5/linux/Documentation/filesystems/vfs.txt Mon Jul 10 16:47:18 2000 +++ linux/Documentation/filesystems/vfs.txt Fri Jul 28 12:50:51 2000 @@ -24,7 +24,7 @@ The Virtual File System (otherwise known as the Virtual Filesystem Switch) is the software layer in the kernel that provides the -filesystem interface to userspace programmes. It also provides an +filesystem interface to userspace programs. It also provides an abstraction within the kernel which allows different filesystem implementations to co-exist. @@ -34,7 +34,7 @@ In this section I'll briefly describe how things work, before launching into the details. I'll start with describing what happens -when user programmes open and manipulate files, and then look from the +when user programs open and manipulate files, and then look from the other view which is how a filesystem is supported and subsequently mounted. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/floppy.txt linux/Documentation/floppy.txt --- v2.4.0-test5/linux/Documentation/floppy.txt Fri Jun 23 21:55:06 2000 +++ linux/Documentation/floppy.txt Fri Jul 28 12:50:51 2000 @@ -88,7 +88,7 @@ If you have a FIFO-able FDC, the floppy driver automatically falls back on non DMA mode if no DMA-able memory can be found. - If you want to avoid this, explicitely ask for 'yesdma'. + If you want to avoid this, explicitly ask for 'yesdma'. floppy=yesdma Tells the floppy driver that a workable DMA channel is available. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/highuid.txt linux/Documentation/highuid.txt --- v2.4.0-test5/linux/Documentation/highuid.txt Fri Jan 21 18:19:15 2000 +++ linux/Documentation/highuid.txt Fri Jul 28 12:50:51 2000 @@ -20,7 +20,7 @@ - Decide whether or not to keep backwards compatibility with the system accounting file, or if we should break it as the comments suggest (currently, the old 16-bit UID and GID are still written to disk, and - part of the former pad sparce is used to store separate 32-bit UID and + part of the former pad space is used to store separate 32-bit UID and GID) - Need to validate that OS emulation calls the 16-bit UID diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/i2c/dev-interface linux/Documentation/i2c/dev-interface --- v2.4.0-test5/linux/Documentation/i2c/dev-interface Sun Mar 19 18:35:30 2000 +++ linux/Documentation/i2c/dev-interface Fri Jul 28 12:50:51 2000 @@ -126,7 +126,7 @@ __s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 *values); __s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length, __u8 *values); -All these tranactions return -1 on failure; you can read errno to see +All these transactions return -1 on failure; you can read errno to see what happened. The 'write' transactions return 0 on success; the 'read' transactions return the read value, except for read_block, which returns the number of values read. The block buffers need not be longer diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/i2c/i2c-protocol linux/Documentation/i2c/i2c-protocol --- v2.4.0-test5/linux/Documentation/i2c/i2c-protocol Thu Feb 10 17:11:02 2000 +++ linux/Documentation/i2c/i2c-protocol Fri Jul 28 12:50:51 2000 @@ -18,7 +18,7 @@ [..]: Data sent by I2C device, as opposed to data sent by the host adapter. -Simple send tranaction +Simple send transaction ====================== This corresponds to i2c_master_send. @@ -34,7 +34,7 @@ S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P -Combined tranactions +Combined transactions ==================== This corresponds to i2c_transfer @@ -54,7 +54,7 @@ Flag I2C_M_NOSTART: In a combined transaction, no 'S Addr' is generated at some point. For example, setting I2C_M_NOSTART on the second partial message - generateds something like: + generates something like: S Addr Rd [A] [Data] NA Wr [A] Data [A] P If you set the I2C_M_NOSTART variable for the first partial message, we do not generate Addr, but we do generate the startbit S. This will diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/i2c/writing-clients linux/Documentation/i2c/writing-clients --- v2.4.0-test5/linux/Documentation/i2c/writing-clients Thu Jul 27 17:37:59 2000 +++ linux/Documentation/i2c/writing-clients Fri Jul 28 12:50:51 2000 @@ -36,7 +36,7 @@ /* dec_use */ &foo_dev_use /* May be NULL */ } -The name can be choosen freely, and may be upto 40 characters long. Please +The name can be chosen freely, and may be upto 40 characters long. Please use something descriptive here. The id should be a unique ID. The range 0xf000 to 0xffff is reserved for @@ -659,7 +659,7 @@ Command function ================ -A generic ioctl-like function call back is supported. You will seldomly +A generic ioctl-like function call back is supported. You will seldom need this. You may even set it to NULL. /* No commands defined */ @@ -733,7 +733,7 @@ u8 command, u8 length, u8 *values); -All these tranactions return -1 on failure. The 'write' transactions +All these transactions return -1 on failure. The 'write' transactions return 0 on success; the 'read' transactions return the read value, except for read_block, which returns the number of values read. The block buffers need not be longer than 32 bytes. @@ -749,7 +749,7 @@ before. /* This call returns a unique low identifier for each registered adapter, - * or -1 if the adapter was not regisitered. + * or -1 if the adapter was not registered. */ extern int i2c_adapter_id(struct i2c_adapter *adap); @@ -791,7 +791,7 @@ fourth should always be 0. The fifth is the mode of the /proc file; 0644 is safe, as the file will be owned by root:root. -The seventh and eigth parameters should be &sensors_proc_real and +The seventh and eighth parameters should be &sensors_proc_real and &sensors_sysctl_real if you want to export lists of reals (scaled integers). You can also use your own function for them, as usual. Finally, the last parameter is the call-back to gather the data diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/ia64/README linux/Documentation/ia64/README --- v2.4.0-test5/linux/Documentation/ia64/README Thu Feb 10 17:11:02 2000 +++ linux/Documentation/ia64/README Fri Aug 4 11:23:37 2000 @@ -57,8 +57,8 @@ table and only if that fails fall back on walking the page table tree. - o Discontigous large memory support; memory above 4GB will be - discontigous since the 4GB-64MB is reserved for firmware and I/O + o Discontiguous large memory support; memory above 4GB will be + discontiguous since the 4GB-64MB is reserved for firmware and I/O space. o Correct mapping for PAL runtime code; PAL code needs to be diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/ia64/efirtc.txt linux/Documentation/ia64/efirtc.txt --- v2.4.0-test5/linux/Documentation/ia64/efirtc.txt Wed Apr 26 16:34:06 2000 +++ linux/Documentation/ia64/efirtc.txt Fri Jul 28 12:50:51 2000 @@ -36,7 +36,7 @@ expose this new way of representing time. Instead we use something very similar to the struct tm, i.e. struct rtc_time, as used by hwclock. One of the reasons for doing it this way is to allow for EFI to still evolve -without necessarily impatcing any of the user applications. The decoupling +without necessarily impacting any of the user applications. The decoupling enables flexibility and permits writing wrapper code is ncase things change. The driver exposes two interfaces, one via the device file and a set of ioctl()s. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/isdn/00-INDEX linux/Documentation/isdn/00-INDEX --- v2.4.0-test5/linux/Documentation/isdn/00-INDEX Wed Feb 16 17:03:51 2000 +++ linux/Documentation/isdn/00-INDEX Fri Jul 28 12:50:51 2000 @@ -31,7 +31,7 @@ README.eicon - info on driver for Eicon active cards. README.concap - - info on "CONCAP" ecapsulation protocol interface used for X.25. + - info on "CONCAP" encapsulation protocol interface used for X.25. README.diversion - info on module for isdn diversion services. README.sc diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/isdn/INTERFACE.fax linux/Documentation/isdn/INTERFACE.fax --- v2.4.0-test5/linux/Documentation/isdn/INTERFACE.fax Thu Aug 12 09:42:33 1999 +++ linux/Documentation/isdn/INTERFACE.fax Fri Jul 28 12:50:51 2000 @@ -4,7 +4,7 @@ Description of the fax-subinterface between linklevel and hardwarelevel of isdn4linux. - The communication between linklevel (LL) and harwarelevel (HL) for fax + The communication between linklevel (LL) and hardwarelevel (HL) for fax is based on the struct T30_s (defined in isdnif.h). This struct is allocated in the LL. In order to use fax, the LL provides the pointer to this struct with the @@ -60,7 +60,7 @@ depending on progress and type of connection. If the phase changes because of an AT command, the LL driver changes this value. Otherwise the HL-driver takes care of it, but - only neccessary on call establishment (from IDLE to PHASE_A). + only necessary on call establishment (from IDLE to PHASE_A). (one of the constants ISDN_FAX_PHASE_[IDLE,A,B,C,D,E]) - direction diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/isdn/README linux/Documentation/isdn/README --- v2.4.0-test5/linux/Documentation/isdn/README Wed Feb 16 17:03:51 2000 +++ linux/Documentation/isdn/README Fri Jul 28 12:50:51 2000 @@ -146,7 +146,7 @@ x = 38400: 198 Note on value in Reg 19: There is _NO_ common convention for 38400 baud. - The value 198 is choosen arbitrarily. Users + The value 198 is chosen arbitrarily. Users _MUST_ negotiate this value before establishing a connection. AT&Sx Set window-size (x = 1..8) (not yet implemented) diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/isdn/README.HiSax linux/Documentation/isdn/README.HiSax --- v2.4.0-test5/linux/Documentation/isdn/README.HiSax Wed Feb 16 17:03:51 2000 +++ linux/Documentation/isdn/README.HiSax Fri Jul 28 12:50:51 2000 @@ -77,7 +77,7 @@ If you know other passive cards with the Siemens chipset, please let me know. To use the PNP cards you need the isapnptools. -You can combine any card, if there is no conflict between the ressources +You can combine any card, if there is no conflict between the resources (io, mem, irq). @@ -532,7 +532,7 @@ /sbin/isdnctrl huptimeout isdn0 0 /sbin/isdnctrl l2_prot isdn0 hdlc # Attention you must not set an outgoing number !!! This won't work !!! - # The incomming number is LEASED0 for the first card, LEASED1 for the + # The incoming number is LEASED0 for the first card, LEASED1 for the # second and so on. /sbin/isdnctrl addphone isdn0 in LEASED0 # Here is no need to bind the channel. @@ -551,7 +551,7 @@ Here an example script: #!/bin/sh -# Start/Stop ISDN lesaed line connection +# Start/Stop ISDN leased line connection I4L_AS_MODULE=yes I4L_REMOTE_IS_CISCO=no diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/isdn/README.act2000 linux/Documentation/isdn/README.act2000 --- v2.4.0-test5/linux/Documentation/isdn/README.act2000 Sun May 23 10:03:41 1999 +++ linux/Documentation/isdn/README.act2000 Fri Jul 28 12:50:51 2000 @@ -7,7 +7,7 @@ Version. Currently, only the ISA-Bus version of the card is supported. However MCA and PCMCIA will follow soon. -The ISA-Bus Version uses 8 IO-ports. The base port adress has to be set +The ISA-Bus Version uses 8 IO-ports. The base port address has to be set manually using the DIP switches. Setting up the DIP switches for the IBM Active 2000 ISDN card: diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/isdn/README.avmb1 linux/Documentation/isdn/README.avmb1 --- v2.4.0-test5/linux/Documentation/isdn/README.avmb1 Thu Nov 11 20:11:31 1999 +++ linux/Documentation/isdn/README.avmb1 Fri Jul 28 12:50:51 2000 @@ -175,7 +175,7 @@ subscribe linux-avmb1 in the body. -German documentaion and several scripts can be found at +German documentation and several scripts can be found at ftp://ftp.avm.de/cardware/b1/linux/ Bugs diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/isdn/README.concap linux/Documentation/isdn/README.concap --- v2.4.0-test5/linux/Documentation/isdn/README.concap Wed Aug 18 11:37:57 1999 +++ linux/Documentation/isdn/README.concap Fri Jul 28 12:50:51 2000 @@ -68,7 +68,7 @@ Likewise, a similar encapsulation protocol will frequently be needed by several different interfaces of even different hardware type, e.g. the synchronous ppp implementation used by the isdn driver and the -asyncronous ppp implementation used by the ppp driver have a lot of +asynchronous ppp implementation used by the ppp driver have a lot of similar code in them. By cleanly separating the encapsulation protocol from the hardware specific interface stuff such code could be shared better in future. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/isdn/README.diversion linux/Documentation/isdn/README.diversion --- v2.4.0-test5/linux/Documentation/isdn/README.diversion Thu Aug 12 09:42:33 1999 +++ linux/Documentation/isdn/README.diversion Fri Jul 28 12:50:51 2000 @@ -57,7 +57,7 @@ compared to the mechanism of ipfwadm or ipchains. If a given rule matches the checking process is finished and the rule matching will be applied to the call. - The rules include primary and secondary service indentifiers, called + The rules include primary and secondary service identifiers, called number and subaddress, callers number and subaddress and whether the rule matches to all filtered calls or only those when all B-channel resources are exhausted. @@ -82,7 +82,7 @@ available in some countries (for example germany). Countries requiring the keypad protocol for activating static diversions (like the netherlands) are not supported but may use the tty devices for this purpose. - The dynamic diversion servives may be used in all countries if the provider + The dynamic diversion services may be used in all countries if the provider enables the feature CF (call forwarding). This should work on both MSN- and point-to-point lines. To add and delete rules the additional divertctrl program is needed. This diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/isdn/README.hysdn linux/Documentation/isdn/README.hysdn --- v2.4.0-test5/linux/Documentation/isdn/README.hysdn Wed Feb 16 17:03:51 2000 +++ linux/Documentation/isdn/README.hysdn Fri Jul 28 12:50:51 2000 @@ -92,7 +92,7 @@ 3 -> card is booted and active And the last field (device) shows the name of the ethernet device assigned - to this card. Up to the first successfull boot this field only shows a - + to this card. Up to the first successful boot this field only shows a - to tell that no net device has been allocated up to now. Once a net device has been allocated it remains assigned to this card, even if a card is rebooted and an boot error occurs. @@ -128,12 +128,12 @@ get the cards and drivers log data. Card messages always start with the keyword LOG. All other lines are output from the driver. The driver log data may be redirected to the syslog by selecting the - approriate bitmask. The cards log messages will always be send to this + appropriate bitmask. The cards log messages will always be send to this interface but never to the syslog. A root user may write a decimal or hex (with 0x) value t this file to select desired output options. As mentioned above the cards log dat is always - written to the cardlog file independant of the following options only used + written to the cardlog file independent of the following options only used to check and debug the driver itself: For example: diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/isdn/README.icn linux/Documentation/isdn/README.icn --- v2.4.0-test5/linux/Documentation/isdn/README.icn Sun May 23 10:03:41 1999 +++ linux/Documentation/isdn/README.icn Fri Jul 28 12:50:51 2000 @@ -139,7 +139,7 @@ To load a 4B-card, the same command is used, except a second firmware file is appended to the commandline of icnctrl. - -> After dowloading firmware, the two LEDs at the back cover of the card + -> After downloading firmware, the two LEDs at the back cover of the card (ICN-4B: 4 LEDs) must be blinking intermittently now. If a connection is up, the corresponding led is lit continuously. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/isdn/README.sc linux/Documentation/isdn/README.sc --- v2.4.0-test5/linux/Documentation/isdn/README.sc Tue Apr 28 14:22:04 1998 +++ linux/Documentation/isdn/README.sc Fri Jul 28 12:50:51 2000 @@ -93,7 +93,7 @@ this driver release? Before you can compile, install and use the SpellCaster ISA ISDN driver, you -must ensure that the following software is installed, configuraed and running: +must ensure that the following software is installed, configured and running: - Linux kernel 2.0.20 or later with the required init and ps versions. Please see your distribution vendor for the correct @@ -189,7 +189,7 @@ basic HDLC connection between its two channels. Two network interfaces are created and two routes added between the channels. - i) using the isdnctrl utitity, add an interface with "addif" and + i) using the isdnctrl utility, add an interface with "addif" and name it "isdn0" ii) add the outgoing and inbound telephone numbers iii) set the Layer 2 protocol to hdlc @@ -213,7 +213,7 @@ This file is a script used to configure a BRI ISDN TA to establish a PPP connection between the two channels. The file is almost identical to the HDLC connection example except that the packet - ecapsulation type has to be set. + encapsulation type has to be set. use the same procedure as in the HDLC connection from steps i) to iii) then, after the Layer 2 protocol is set, set the encapsulation @@ -238,7 +238,7 @@ This file is a script used to configure a BRI ISDN TA to accept a Multi Link PPP connection. - i) using the isdnctrl utitity, add an interface with "addif" and + i) using the isdnctrl utility, add an interface with "addif" and name it "ippp0" ii) add the inbound telephone number iii) set the Layer 2 protocol to hdlc and the Layer 3 protocol to diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/joystick-api.txt linux/Documentation/joystick-api.txt --- v2.4.0-test5/linux/Documentation/joystick-api.txt Thu Jul 27 17:37:59 2000 +++ linux/Documentation/joystick-api.txt Fri Jul 28 12:50:51 2000 @@ -29,13 +29,13 @@ where js_event is defined as struct js_event { - __u32 time; /* event timestamp in miliseconds */ + __u32 time; /* event timestamp in milliseconds */ __s16 value; /* value */ __u8 type; /* event type */ __u8 number; /* axis/button number */ }; -If the read is successfull, it will return sizeof(struct js_event), unless +If the read is successful, it will return sizeof(struct js_event), unless you wanted to read more than one event per read as described in section 3.1. @@ -225,7 +225,7 @@ ~~~~~~~~~~~~~~ JSIOCGNAME(len) allows you to get the name string of the joystick - the same -as is being printed at boot time. The 'len' argument is the lenght of the +as is being printed at boot time. The 'len' argument is the length of the buffer provided by the application asking for the name. It is used to avoid possible overrun should the name be too long. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/joystick-parport.txt linux/Documentation/joystick-parport.txt --- v2.4.0-test5/linux/Documentation/joystick-parport.txt Fri Jun 23 21:55:06 2000 +++ linux/Documentation/joystick-parport.txt Fri Jul 28 12:50:51 2000 @@ -22,7 +22,7 @@ 2. Devices supported ~~~~~~~~~~~~~~~~~~~~ - Many console and 8-bit coputer gamepads and joysticks are supported. The + Many console and 8-bit computer gamepads and joysticks are supported. The following subsections discuss usage of each. 2.1 NES and SNES @@ -328,7 +328,7 @@ ~~~~~~~~ All the Sega controllers are more or less based on the standard 2-button Multisystem joystick. However, since they don't use switches and use TTL -logic, the only driver useable with them is the db9.c driver. +logic, the only driver usable with them is the db9.c driver. 2.4.1 Sega Master System ~~~~~~~~~~~~~~~~~~~~~~~~ diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/joystick.txt linux/Documentation/joystick.txt --- v2.4.0-test5/linux/Documentation/joystick.txt Thu Jul 27 17:37:59 2000 +++ linux/Documentation/joystick.txt Fri Jul 28 12:50:51 2000 @@ -166,7 +166,7 @@ It also supports extensions like additional hats and buttons compatible with CH Flightstick Pro, ThrustMaster FCS or 6 and 8 button gamepads. Saitek -Cyborg 'digital' joysticks are also supportted by this driver, because +Cyborg 'digital' joysticks are also supported by this driver, because they're basically souped up CHF sticks. However the only types that can be autodetected are: @@ -475,7 +475,7 @@ inputattach --magellan /dev/tts/x & command. After that the Magellan will be detected, initialized, will beep, -and the /dev/input/jsX device should become useable. +and the /dev/input/jsX device should become usable. 3.17 I-Force devices ~~~~~~~~~~~~~~~~~~~~ @@ -491,7 +491,7 @@ inputattach --iforce /dev/tts/x & command. After that the I-Force device will be detected, and the -/dev/input/jsX device should become useable. +/dev/input/jsX device should become usable. In case you're using the device via the USB port, the inputattach command isn't needed. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/kbuild/commands.txt linux/Documentation/kbuild/commands.txt --- v2.4.0-test5/linux/Documentation/kbuild/commands.txt Mon Feb 1 12:03:20 1999 +++ linux/Documentation/kbuild/commands.txt Fri Jul 28 12:50:51 2000 @@ -84,7 +84,7 @@ occasionally. If you are adding configuration options, it's nice if you do it before you publish your patch! - You can run 'make checkhelp' withoug configuring the kernel. + You can run 'make checkhelp' without configuring the kernel. Also, 'make checkhelp' does not modify any files. make dep, make depend diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/kbuild/config-language.txt linux/Documentation/kbuild/config-language.txt --- v2.4.0-test5/linux/Documentation/kbuild/config-language.txt Tue May 23 15:31:32 2000 +++ linux/Documentation/kbuild/config-language.txt Fri Aug 4 18:38:44 2000 @@ -80,7 +80,7 @@ A /word/ is a single unquoted word, a single-quoted string, or a double-quoted string. If the word is unquoted or double quoted, - then $-substition will be performed on the word. + then $-substitution will be performed on the word. A /symbol/ is a single unquoted word. A symbol must have a name of the form CONFIG_*. scripts/mkdep.c relies on this convention in order @@ -231,7 +231,7 @@ trying to write Config Language scripts with a default value for bool, but *all* of the existing language interpreters discard additional values. Feel free to submit a multi-interpreter patch to linux-kbuild if you -want to implement this as an enhancment. +want to implement this as an enhancement. Configure: implemented Menuconfig: implemented @@ -291,6 +291,7 @@ This verb displays /prompt/ to the user, accepts a value from the user, and assigns that value to /symbol/. /word/ is the default value. Legal input values are any ASCII string, except for the characters '"' and '\\'. +Configure will trap an input string of "?" to display help. The default value is mandatory. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/kernel-parameters.txt linux/Documentation/kernel-parameters.txt --- v2.4.0-test5/linux/Documentation/kernel-parameters.txt Thu Jul 27 17:37:59 2000 +++ linux/Documentation/kernel-parameters.txt Fri Aug 4 15:37:48 2000 @@ -20,6 +20,8 @@ EIDE EIDE/ATAPI support is enabled. FB The frame buffer device is enabled. HW Appropriate hardware is enabled. + IA-32 IA-32 aka i386 architecture is enabled. + IA-64 IA-64 architecture is enabled. ISDN Appropriate ISDN support is enabled. JOY Appropriate joystick support is enabled. LP Printer support is enabled. @@ -396,7 +398,36 @@ pcd. [PARIDE] - pci= [PCI] + pci=option[,option...] [PCI] various PCI subsystem options: + off [IA-32] don't probe for the PCI bus + bios [IA-32] force use of PCI BIOS, don't access + the hardware directly. Use this if your machine + has a non-standard PCI host bridge. + nobios [IA-32] disallow use of PCI BIOS, only direct + hardware access methods are allowed. Use this + if you experience crashes upon bootup and you + suspect they are caused by the BIOS. + conf1 [IA-32] Force use of PCI Configuration Mechanism 1. + conf2 [IA-32] Force use of PCI Configuration Mechanism 2. + nosort [IA-32] Don't sort PCI devices according to + order given by the PCI BIOS. This sorting is done + to get a device order compatible with older kernels. + biosirq [IA-32] Use PCI BIOS calls to get the interrupt + routing table. These calls are known to be buggy + on several machines and they hang the machine when used, + but on other computers it's the only way to get the + interrupt routing table. Try this option if the kernel + is unable to allocate IRQs or discover secondary PCI + buses on your motherboard. + rom [IA-32] Assign address space to expansion ROMs. + Use with caution as certain devices share address + decoders between ROMs and other resources. + irqmask=0xMMMM [IA-32] Set a bit mask of IRQs allowed to be assigned + automatically to PCI devices. You can make the kernel + exclude IRQs of your ISA cards this way. + lastbus=N [IA-32] Scan all buses till bus #N. Can be useful + if the kernel is unable to find your secondary buses + and you want to tell it explicitly which ones they are. pd. [PARIDE] diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/m68k/README.buddha linux/Documentation/m68k/README.buddha --- v2.4.0-test5/linux/Documentation/m68k/README.buddha Sat Feb 26 22:31:37 2000 +++ linux/Documentation/m68k/README.buddha Fri Jul 28 12:50:51 2000 @@ -21,7 +21,7 @@ The card should be a Z-II board, size 64K, not for freemem list, Rom-Vektor is valid, no second Autoconfig-board on the -same card, no space preferrence, supports "Shutup_forever". +same card, no space preference, supports "Shutup_forever". Setting the base address should be done in two steps, just as the Amiga Kickstart does: The lower nibble of the 8-Bit @@ -29,7 +29,7 @@ $48, while it doesn't matter how often you're writing to $4a as long as $48 is not touched. After $48 has been written, the whole card disappears from $e8 and is mapped to the new -addrress just written. Make shure $4a is written befor $48, +address just written. Make shure $4a is written before $48, otherwise your chance is only 1:16 to find the board :-). The local memory-map is even active when mapped to $e8: @@ -100,7 +100,7 @@ for Buddha-only) registers $f00, $f40 and $f80. This way more than one I/O request can be handled and you can easily determine what driver has to serve the INT2. Buddha and -Catweasel expansion boards can issue an INT6. A seperate +Catweasel expansion boards can issue an INT6. A separate memory map is available for the I/O module and the sysop's I/O module. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/m68k/kernel-options.txt linux/Documentation/m68k/kernel-options.txt --- v2.4.0-test5/linux/Documentation/m68k/kernel-options.txt Tue May 11 09:57:14 1999 +++ linux/Documentation/m68k/kernel-options.txt Fri Jul 28 12:50:51 2000 @@ -482,7 +482,7 @@ xres_virtual must be set to 2048. For ET4000, xres_virtual depends on the initialisation of the video-card. If you're missing a corresponding yres_virtual: the external part is legacy, -therefore we don't support hardware-dependend functions like hardware-scroll, +therefore we don't support hardware-dependent functions like hardware-scroll, panning or blanking. 4.1.7) eclock: diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/md.txt linux/Documentation/md.txt --- v2.4.0-test5/linux/Documentation/md.txt Fri Jun 23 21:55:06 2000 +++ linux/Documentation/md.txt Fri Jul 28 12:50:51 2000 @@ -6,7 +6,7 @@ You can boot (if you selected boot support in the configuration) with your md device with the following kernel command lines: -for old raid arrays without persistant superblocks: +for old raid arrays without persistent superblocks: md=,,,,dev0,dev1,...,devn for raid arrays with persistant superblocks diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/moxa-smartio linux/Documentation/moxa-smartio --- v2.4.0-test5/linux/Documentation/moxa-smartio Fri Jan 21 18:19:15 2000 +++ linux/Documentation/moxa-smartio Fri Jul 28 12:50:51 2000 @@ -23,7 +23,7 @@ -C168P/H/HS, C168H/PCI 8 port multiport board. This driver has been modified a little and cleaned up from the Moxa - contributed driver code and merged into Linux 2.2.14pre. In paticular + contributed driver code and merged into Linux 2.2.14pre. In particular official major/minor numbers have been assigned which are different to those the original Moxa supplied driver used. @@ -83,7 +83,7 @@ PCI board --------- - You may need to adjust IRQ useage in BIOS to avoid from IRQ conflict + You may need to adjust IRQ usage in BIOS to avoid from IRQ conflict with other ISA devices. Please refer to hardware installation procedure in User's Manual in advance. @@ -150,7 +150,7 @@ # insmod mxser - to activate the moduler driver. You may run "lsmod" to check + to activate the modular driver. You may run "lsmod" to check if "mxser.o" is activated. 2. Create special files by executing "msmknod". @@ -158,7 +158,7 @@ # ./msmknod Default major numbers for dial-in device and callout device are - 174, 175. Msmknod will delete any special files occuping the same + 174, 175. Msmknod will delete any special files occupying the same device naming. 3. Up to now, you may manually execute "insmod mxser" to activate @@ -209,7 +209,7 @@ below. a. # cd /moxa/mxser/driver # vi mxser.c - b. Find the array mxserBoardCAP[] as belows. + b. Find the array mxserBoardCAP[] as below. static int mxserBoardCAP[] = {0x00, 0x00, 0x00, 0x00}; @@ -260,7 +260,7 @@ f. cp /usr/src/linux/arch/i386/boot/bzImage /boot/vmlinuz g. Please make sure the boot kernel (vmlinuz) is in the correct position. If you use 'lilo' utility, you should - check /etc/lilo.conf 'image' item specifiedd the path + check /etc/lilo.conf 'image' item specified the path which is the 'vmlinuz' path, or you will load wrong (or old) boot kernel image (vmlinuz). h. chmod 400 /vmlinuz @@ -372,7 +372,7 @@ ----------------------------------------------------------------------------- 6. Troubleshooting - The boot time error mesages and solutions are stated as clearly as + The boot time error messages and solutions are stated as clearly as possible. If all the possible solutions fail, please contact our technical support team to get more help. @@ -388,7 +388,7 @@ which device causes the situation,please check /proc/interrupts to find free IRQ and simply change another free IRQ for Moxa board. - Error msg: Board #: C1xx Series(CAP=xxx) interupt number invalid. + Error msg: Board #: C1xx Series(CAP=xxx) interrupt number invalid. Solution: Each port within the same multiport board shares the same IRQ. Please set one IRQ (IRQ doesn't equal to zero) for one Moxa board. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/mtrr.txt linux/Documentation/mtrr.txt --- v2.4.0-test5/linux/Documentation/mtrr.txt Thu Aug 5 14:34:01 1999 +++ linux/Documentation/mtrr.txt Fri Jul 28 12:50:51 2000 @@ -31,7 +31,7 @@ There are two interfaces to /proc/mtrr: one is an ASCII interface which allows you to read and write. The other is an ioctl() interface. The ASCII interface is meant for administration. The -ioctl() interface is meant for C programmes (i.e. the X server). The +ioctl() interface is meant for C programs (i.e. the X server). The interfaces are described below, with sample commands and C code. =============================================================================== @@ -96,11 +96,11 @@ or using bash: % echo "disable=2" >| /proc/mtrr =============================================================================== -Reading MTRRs from a C programme using ioctl()'s: +Reading MTRRs from a C program using ioctl()'s: /* mtrr-show.c - Source file for mtrr-show (example programme to show MTRRs using ioctl()'s) + Source file for mtrr-show (example program to show MTRRs using ioctl()'s) Copyright (C) 1997-1998 Richard Gooch @@ -124,7 +124,7 @@ */ /* - This programme will use an ioctl() on /proc/mtrr to show the current MTRR + This program will use an ioctl() on /proc/mtrr to show the current MTRR settings. This is an alternative to reading /proc/mtrr. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/networking/README.sb1000 linux/Documentation/networking/README.sb1000 --- v2.4.0-test5/linux/Documentation/networking/README.sb1000 Mon Oct 4 15:49:29 1999 +++ linux/Documentation/networking/README.sb1000 Fri Jul 28 12:50:51 2000 @@ -30,7 +30,7 @@ http://home.adelphia.net/~siglercm/sb1000.html http://linuxpower.cx/~cable/ - along with these utilties. + along with these utilities. 3.) The standard isapnp tools. These are necessary to configure your SB1000 card at boot time (or afterwards by hand) since it's a PnP card. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/networking/comx.txt linux/Documentation/networking/comx.txt --- v2.4.0-test5/linux/Documentation/networking/comx.txt Tue Mar 14 19:10:38 2000 +++ linux/Documentation/networking/comx.txt Fri Jul 28 12:50:51 2000 @@ -63,7 +63,7 @@ When you're ready with filling in the files in the comx[n] directory, you can configure the corresponding network interface with the standard network -configuration utilites. If you're unble to bring the interfaces up, look up +configuration utilities. If you're unable to bring the interfaces up, look up the various kernel log files on your system, and consult the messages for a probable reason. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/networking/cs89x0.txt linux/Documentation/networking/cs89x0.txt --- v2.4.0-test5/linux/Documentation/networking/cs89x0.txt Tue Mar 7 14:32:25 2000 +++ linux/Documentation/networking/cs89x0.txt Fri Jul 28 12:50:51 2000 @@ -214,7 +214,7 @@ insmod cs89x0.o io=0x200 irq=0xA media=aui -This exmaple loads the module and configures the adapter to use an IO port base +This example loads the module and configures the adapter to use an IO port base address of 200h, interrupt 10, and use the AUI media connection. The following configuration options are available on the command line: @@ -259,7 +259,7 @@ irq media type (no autodetect) -f) The following addtional parameters are CS89XX defaults (values +f) The following additional parameters are CS89XX defaults (values used with no EEPROM or command-line argument). * DMA Burst = enabled diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/networking/decnet.txt linux/Documentation/networking/decnet.txt --- v2.4.0-test5/linux/Documentation/networking/decnet.txt Mon Jul 10 16:47:18 2000 +++ linux/Documentation/networking/decnet.txt Fri Jul 28 12:50:51 2000 @@ -44,7 +44,7 @@ the two numbers are the node address 1,2 = 1.2 For 2.2.xx kernels and early 2.3.xx kernels, you must use a comma when specifying the DECnet address like this. For more recent 2.3.xx kernels, you may -use almost charecter except space, although a `.` would be the most +use almost any character except space, although a `.` would be the most obvious choice :-) There used to be a third number specifying the node type. This option diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/networking/dmfe.txt linux/Documentation/networking/dmfe.txt --- v2.4.0-test5/linux/Documentation/networking/dmfe.txt Wed Apr 26 16:34:06 2000 +++ linux/Documentation/networking/dmfe.txt Fri Jul 28 12:50:51 2000 @@ -25,7 +25,7 @@ -Wall -Wstrict-prototypes -O6 -c dmfe.c" - B. The following steps teach you how to active DM9102 board: + B. The following steps teach you how to activate a DM9102 board: 1. Used the upper compiler command to compile dmfe.c @@ -40,13 +40,13 @@ "ifconfig eth0 172.22.3.18" ^^^^^^^^^^^ Your IP address - 4. Active the IP routing table. For some distributions, it is not + 4. Activate the IP routing table. For some distributions, it is not necessary. You can type "route" to check. "route add default eth0" - 5. Well done. Your DM9102 adapter actived now. + 5. Well done. Your DM9102 adapter is now activated. C. Object files description: diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/networking/ethertap.txt linux/Documentation/networking/ethertap.txt --- v2.4.0-test5/linux/Documentation/networking/ethertap.txt Fri Jan 7 19:13:21 2000 +++ linux/Documentation/networking/ethertap.txt Fri Aug 4 13:13:16 2000 @@ -1,88 +1,262 @@ -Documentation on setup and use of EtherTap. +Ethertap programming mini-HOWTO +------------------------------- -Contact Jay Schulist if you -have questions or need futher assistance. +The ethertap driver was written by Jay Schulist , +you should contact him for further information. This document was written by +bert hubert . Updates are welcome. -Introduction -============ +What ethertap can do for you +---------------------------- -Ethertap provides packet reception and transmission for user -space programs. It can be viewed as a simple Ethernet device, -which instead of receiving packets from a network wire, it receives -them from user space. +Ethertap allows you to easily run your own network stack from userspace. +Tunnels can benefit greatly from this. You can also use it to do network +experiments. The alternative would be to use a raw socket to send data and +use libpcap to receive it. Using ethertap saves you this multiplicity and +also does ARP for you if you want. -Ethertap can be used for anything from AppleTalk to IPX to even -building bridging tunnels. It also has many other general purpose -uses. +The more technical blurb: -Ethertap also can do ARP for you, although this is not enabled by -default. +Ethertap provides packet reception and transmission for user space programs. +It can be viewed as a simple Ethernet device, which instead of receiving +packets from a network wire, it receives them from user space. -SetUp -===== +Ethertap can be used for anything from AppleTalk to IPX to even building +bridging tunnels. It also has many other general purpose uses. -First you will have to enable Ethertap in the kernel configuration. -Then you will need to create any number of ethertap device files, -/dev/tap0->/dev/tap15. This is done by the following command. +Configuring your kernel +----------------------- -mknod /dev/tap* c 36 16 ( 17 18 19 20 for tap1,2,3,4...) +Firstly, you need this in Networking Options: -** Replace * with the proper tap device number you need. ** + # + # Code maturity level options + # + CONFIG_EXPERIMENTAL=y -Now with your kernel that has ethertap enabled, you will need -to ifconfig /dev/tap* 192.168.1.1 (replace 192.168.1.1 with the -proper IP number for your situation.) +Then you need Netlink support: -If you want your Ethertap device to ARP for you would ifconfig -the interface like this: ifconfig tap* 192.168.1.1 arp + CONFIG_NETLINK=y -Remember that you need to have a corresponding /dev/tap* file -for each tap* device you need to ifconfig. +This allows the kernel to exchange data with userspace applications. There +are two ways of doing this, the new way works with netlink sockets and I +have no experience with that yet. ANK uses it in his excellent iproute2 +package, see for example rtmon.c. iproute2 can be found on +ftp://ftp.inr.ac.ru/ip-routing/iproute2* -Now Ethertap should be ready to use. +The new way is described, partly in netlink(7), available on +http://www.europe.redhat.com/documentation/man-pages/man7/netlink.7.php3 -Diagram of how Ethertap works. (Courtesy of Alan Cox) -==================================================== +There is also a Netlink-HOWTO, available on http://snafu.freedom.org/linux2.2/docs/netlink-HOWTO.html +Sadly I know of no code using ethertap with this new interface. -This is for a tunnel, but you should be able to -get the general idea. +The older way works by opening character special files with major node 36. +Enable this with: - 1.2.3.4 will be the router to the outside world - 1.2.3.5 our box - 2.0.0.1 our box (appletalk side) - 2.0.0.* a pile of macintoys + CONFIG_NETLINK_DEV=m +Please be advised that this support is going to be dropped somewhere in the +future! -[1.2.3.4]-------------1.2.3.5[Our Box]2.0.0.1---------> macs +Then finally in the Network Devices section, -The routing on our box would be + CONFIG_ETHERTAP=m - ifconfig eth0 1.2.3.5 netmask 255.255.255.0 up - route add default gw 1.2.3.4 - ifconfig tap0 2.0.0.1 netmask 255.255.255.0 up arp - (route add 2.0.0.0 netmask 255.255.255.0) +You can include it directly in the kernel if you want, of course, no need +for modules. -C code for a Simple program using an EtherTap device -==================================================== +Setting it all up +----------------- -This code is just excerpts from a real program, so some parts are missing -but the important stuff is below. +First we need to create the /dev/tap0 device node: -void main (void) -{ - int TapDevice, eth_pkt_len = 0; - unsigned char full_pkt_len[MAX_PKT_LEN]; + # mknod /dev/tap0 c 36 16 + # mknod /dev/tap1 c 36 17 + (etc) + +Include the relevant modules (ethertap.o, netlink_dev.o, perhaps netlink.o), +and bring up your tap0 device: + + # ifconfig tap0 10.0.0.123 up + +Now your device is up and running, you can ping it as well. This is what +confused me to no end, because nothing is connected to our ethertap as yet, +how is it that we can ping it? + +It turns out that the ethertap is just like a regular network interface - +even when it's down you can ping it. We need to route stuff to it: + + # route add -host 10.0.0.124 gw 10.0.0.123 + +Now we can read /dev/tap0 and when we ping 10.0.0.124 from our +localhost, output should appear on the screen. + + # cat /dev/tap0 + :ßVU:9````````````````````````þýþET@?' + + +Getting this to work from other hosts +------------------------------------- + +For this to work, you often need proxy ARP. + + # echo 1 > /proc/sys/net/ipv4/conf/eth0/proxy_arp + +eth0 here stands for the interface that connects to 'other hosts'. - TapDevice = open("/dev/tap0", O_RDWR); - if(TapDevice < 0) - { - perror("Error opening device"); - exit(1); - } +Chances are that you are trying this on a non-routing desktop computer, so +you need to enable ip forwarding: - write(TapDevice, full_packet, eth_pkt_len); + # echo 1 > /proc/sys/net/ipv4/ip_forward - close(TapDevice); +You should now be able to ping 10.0.0.124 from other hosts on your +10.0.0.0/8 subnet. If you are using public ip space, it should work from +everywhere. - return; +ARP +--- + +If we were to take things very literally, your tcp/ip pseudo stack would +also have to implement ARP and MAC addresses. This is often a bit silly as +the ethertap device is a figment of our imagination anyway. However, should +you want to go 'all the way', you can add the 'arp' flag to ifconfig: + + # ifconfig tap0 10.0.0.123 up arp + +This may also be useful when implementing a bridge, which needs to bridge +ARP packets as well. + +The sample program below will no longer work then, because it does not +implement ARP. + +Sample program +-------------- + +A sample program is included somewhere in the bowels of the netfilter +source. I've extracted this program and list it here. It implements a very +tiny part of the IP stack and can respond to any pings it receives. It gets +confused if it receives ARP, as it tries to parse it by treating it as an IP +packet. + +/* Simple program to listen to /dev/tap0 and reply to pings. */ +#include +#include +#include +#if defined(__GLIBC__) && (__GLIBC__ == 2) +#include +#include +#else +#include +#include +#endif +#include +#include +#include +#include + +u_int16_t csum_partial(void *buffer, unsigned int len, u_int16_t prevsum) +{ + u_int32_t sum = 0; + u_int16_t *ptr = buffer; + + while (len > 1) { + sum += *ptr++; + len -= 2; + } + if (len) { + union { + u_int8_t byte; + u_int16_t wyde; + } odd; + odd.wyde = 0; + odd.byte = *((u_int8_t *)ptr); + sum += odd.wyde; + } + sum = (sum >> 16) + (sum & 0xFFFF); + sum += prevsum; + return (sum + (sum >> 16)); +} + +int main() +{ + int fd, len; + union { + struct { + char etherhdr[16]; + struct iphdr ip; + } fmt; + unsigned char raw[65536]; + } u; + + fd = open("/dev/tap0", O_RDWR); + if (fd < 0) { + perror("Opening `/dev/tap0'"); + return 1; + } + + /* u.fmt.ip.ihl in host order! Film at 11. */ + while ((len = read(fd, &u, sizeof(u))) > 0) { + u_int32_t tmp; + struct icmphdr *icmp + = (void *)((u_int32_t *)&u.fmt.ip + u.fmt.ip.ihl ); + struct tcphdr *tcp = (void *)icmp; + struct udphdr *udp = (void *)icmp; + + fprintf(stderr, "SRC = %u.%u.%u.%u DST = %u.%u.%u.%u\n", + (ntohl(u.fmt.ip.saddr) >> 24) & 0xFF, + (ntohl(u.fmt.ip.saddr) >> 16) & 0xFF, + (ntohl(u.fmt.ip.saddr) >> 8) & 0xFF, + (ntohl(u.fmt.ip.saddr) >> 0) & 0xFF, + (ntohl(u.fmt.ip.daddr) >> 24) & 0xFF, + (ntohl(u.fmt.ip.daddr) >> 16) & 0xFF, + (ntohl(u.fmt.ip.daddr) >> 8) & 0xFF, + (ntohl(u.fmt.ip.daddr) >> 0) & 0xFF); + + switch (u.fmt.ip.protocol) { + case IPPROTO_ICMP: + if (icmp->type == ICMP_ECHO) { + fprintf(stderr, "PONG! (iphdr = %u bytes)\n", + (unsigned int)((char *)icmp + - (char *)&u.fmt.ip)); + + /* Turn it around */ + tmp = u.fmt.ip.saddr; + u.fmt.ip.saddr = u.fmt.ip.daddr; + u.fmt.ip.daddr = tmp; + + icmp->type = ICMP_ECHOREPLY; + icmp->checksum = 0; + icmp->checksum + = ~csum_partial(icmp, + ntohs(u.fmt.ip.tot_len) + - u.fmt.ip.ihl*4, 0); + + { + unsigned int i; + for (i = 44; + i < ntohs(u.fmt.ip.tot_len); i++){ + printf("%u:0x%02X ", i, + ((unsigned char *) + &u.fmt.ip)[i]); + } + printf("\n"); + } + write(fd, &u, len); + } + break; + case IPPROTO_TCP: + fprintf(stderr, "TCP: %u -> %u\n", ntohs(tcp->source), + ntohs(tcp->dest)); + break; + + case IPPROTO_UDP: + fprintf(stderr, "UDP: %u -> %u\n", ntohs(udp->source), + ntohs(udp->dest)); + break; + } + } + if (len < 0) + perror("Reading from `/dev/tap0'"); + else fprintf(stderr, "Empty read from `/dev/tap0'"); + return len < 0 ? 1 : 0; } + diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/networking/ip-sysctl.txt linux/Documentation/networking/ip-sysctl.txt --- v2.4.0-test5/linux/Documentation/networking/ip-sysctl.txt Fri Jan 28 15:09:06 2000 +++ linux/Documentation/networking/ip-sysctl.txt Fri Jul 28 12:50:51 2000 @@ -88,7 +88,7 @@ will be aborted after ~11 minutes of retries. tcp_retries1 - INTEGER - How many times to retry before deciding that somethig is wrong + How many times to retry before deciding that something is wrong and it is necessary to report this suspection to network layer. Minimal RFC value is 3, it is default, which corresponds to ~3sec-8min depending on RTO. @@ -139,13 +139,13 @@ (probably, after increasing installed memory), if network conditions require more than default value, and tune network services to linger and kill such states - more aggressivley. Let me to remind again: each orphan eats + more aggressively. Let me to remind again: each orphan eats up to ~64K of unswappable memory. tcp_abort_on_overflow - BOOLEAN If listening service is too slow to accept new connections, reset them. Default state is FALSE. It means that if overflow - occured due to a burst, connection will recover. Enable this + occurred due to a burst, connection will recover. Enable this option _only_ if you are really sure that listening daemon cannot be tuned to accept connections faster. Enabling this option can harm clients of your server. @@ -179,7 +179,7 @@ tcp_max_syn_backlog - INTEGER Maximal number of remembered connection requests, which are - still did not receive an acknowldgement from connecting client. + still did not receive an acknowledgement from connecting client. Default value is 1024 for systems with more than 128Mb of memory, and 128 for low memory machines. If server suffers of overload, try to increase this number. Warning! If you make it greater diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/networking/ipddp.txt linux/Documentation/networking/ipddp.txt --- v2.4.0-test5/linux/Documentation/networking/ipddp.txt Fri Jan 7 19:13:21 2000 +++ linux/Documentation/networking/ipddp.txt Fri Jul 28 12:50:51 2000 @@ -1,7 +1,7 @@ Text file for ipddp.c: AppleTalk-IP Decapsulation and AppleTalk-IP Encapsulation -This text file writen by Jay Schulist +This text file is written by Jay Schulist Introduction ------------ diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/networking/iphase.txt linux/Documentation/networking/iphase.txt --- v2.4.0-test5/linux/Documentation/networking/iphase.txt Thu Feb 10 17:11:02 2000 +++ linux/Documentation/networking/iphase.txt Fri Jul 28 12:50:51 2000 @@ -137,7 +137,7 @@ -Pcbr:max_pcr= where: xxx = the maximum peak cell rate, from 170 - 353207. - This option may only be set on the trasmit machine. + This option may only be set on the transmit machine. OUTSTANDING ISSUES diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/networking/olympic.txt linux/Documentation/networking/olympic.txt --- v2.4.0-test5/linux/Documentation/networking/olympic.txt Mon Jul 5 19:54:55 1999 +++ linux/Documentation/networking/olympic.txt Fri Jul 28 12:50:51 2000 @@ -38,14 +38,14 @@ message_level: Controls level of messages created by the driver. Defaults to 0: which only displays start-up and critical messages. Presently any non-zero value will display all soft messages as well. NB This does not turn -debuging messages on, that must be done by modified the source code. +debugging messages on, that must be done by modified the source code. Multi-card: The driver will detect multiple cards and will work with shared interrupts, each card is assigned the next token ring device, i.e. tr0 , tr1, tr2. The driver should also happily reside in the system with other drivers. It has -been tested with ibmtr.c running, and I personnally have had one Olicom PCI +been tested with ibmtr.c running, and I personally have had one Olicom PCI card and two IBM olympic cards (all on the same interrupt), all running together. @@ -68,7 +68,7 @@ by the driver and the source and destination addresses printed. Also an entry will be added in /proc/net called olympic_tr. This displays low level information about the configuration of the ring and -the adapter. This feature has been designed for network adiministrators +the adapter. This feature has been designed for network administrators to assist in the diagnosis of network / ring problems. 6/8/99 Peter De Schrijver and Mike Phillips diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/networking/shaper.txt linux/Documentation/networking/shaper.txt --- v2.4.0-test5/linux/Documentation/networking/shaper.txt Fri Jun 23 21:55:06 2000 +++ linux/Documentation/networking/shaper.txt Fri Jul 28 12:50:51 2000 @@ -42,7 +42,7 @@ There is no "borrowing" or "sharing" scheme. This is a simple traffic limiter. We implement Van Jacobson and Sally Floyd's CBQ -architecture into Linux 2.2. THis is the preferred solution. Shaper is +architecture into Linux 2.2. This is the preferred solution. Shaper is for simple or back compatible setups. Alan diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/networking/sis900.txt linux/Documentation/networking/sis900.txt --- v2.4.0-test5/linux/Documentation/networking/sis900.txt Wed Dec 29 13:13:12 1999 +++ linux/Documentation/networking/sis900.txt Fri Jul 28 12:50:52 2000 @@ -161,7 +161,7 @@ Silicon Integrated System Corp. is cooperating closely with core Linux Kernel developers. The revisions of SiS 900 driver are distributed by - the usuall channels for kernel tar files and patches. Those kernel tar + the usual channels for kernel tar files and patches. Those kernel tar files for official kernel and patches for kernel pre-release can be download at official kernel ftp site and its mirrors. The 1.06 diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/networking/sk98lin.txt linux/Documentation/networking/sk98lin.txt --- v2.4.0-test5/linux/Documentation/networking/sk98lin.txt Fri Jun 23 21:55:06 2000 +++ linux/Documentation/networking/sk98lin.txt Fri Jul 28 12:50:52 2000 @@ -138,7 +138,7 @@ options sk98lin ... For "...", use the same syntax as described below for the command -line paramaters of insmod. +line parameters of insmod. You either have to reboot your computer or unload and reload the driver to activate the new parameters. The syntax of the driver parameters is: @@ -187,7 +187,7 @@ this port is not "Sense". If autonegotiation is "On", all three values are possible. If it is "Off", only "Full" and "Half" are allowed. - It is usefull if your link partner does not support all + It is useful if your link partner does not support all possible combinations. - Flow Control @@ -269,7 +269,7 @@ Large frames (also called jumbo frames) are now supported by the driver. This can result in a greatly improved throughput if -transfering large amounts of data. +transferring large amounts of data. To enable large frames, set the MTU (maximum transfer unit) of the interface to the value you wish (up to 9000). The command for this is: @@ -285,7 +285,7 @@ You can switch back to the standard ethernet frame size with: ifconfig eth0 mtu 1500 -To make this setting persitent, add a script with the 'ifconfig' +To make this setting persistent, add a script with the 'ifconfig' line to the system startup sequence (named something like "S99sk98lin" in /etc/rc.d/rc2.d). *** diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/networking/smctr.txt linux/Documentation/networking/smctr.txt --- v2.4.0-test5/linux/Documentation/networking/smctr.txt Fri Jan 28 15:09:06 2000 +++ linux/Documentation/networking/smctr.txt Fri Jul 28 12:50:52 2000 @@ -62,5 +62,5 @@ This driver is under the GNU General Public License. Its Firmware image is included as an initialized C-array and is licensed by SMC to the Linux -users of this driver. However no waranty about its fitness is expressed or +users of this driver. However no warranty about its fitness is expressed or implied by SMC. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/networking/tlan.txt linux/Documentation/networking/tlan.txt --- v2.4.0-test5/linux/Documentation/networking/tlan.txt Fri Jun 23 21:55:06 2000 +++ linux/Documentation/networking/tlan.txt Fri Jul 28 12:50:52 2000 @@ -51,7 +51,7 @@ 0x01 Turn on general debugging messages. 0x02 Turn on receive debugging messages. 0x04 Turn on transmit debugging messages. - 0x08 Turn on list debugging messsages. + 0x08 Turn on list debugging messages. 2. You can append aui=1 to the end of the insmod line to cause the adapter to use the AUI interface instead of the 10 Base T diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/networking/tms380tr.txt linux/Documentation/networking/tms380tr.txt --- v2.4.0-test5/linux/Documentation/networking/tms380tr.txt Fri Jan 7 19:13:21 2000 +++ linux/Documentation/networking/tms380tr.txt Fri Jul 28 12:50:52 2000 @@ -10,8 +10,8 @@ http://www.linux-sna.org Many thanks to Christoph Goos for his excellent work on this driver and -SysKonnect for donating the adapters to Linux-SNA for the testing and maintaince -of this device driver. +SysKonnect for donating the adapters to Linux-SNA for the testing and +maintenance of this device driver. Important information to be noted: 1. Adapters can be slow to open (~20 secs) and close (~5 secs), please be @@ -52,7 +52,7 @@ This driver is under the GNU General Public License. Its Firmware image is included as an initialized C-array and is licensed by SysKonnect to the Linux -users of this driver. However no waranty about its fitness is expressed or +users of this driver. However no warranty about its fitness is expressed or implied by SysKonnect. Below find attached the setting for the SK NET TR 4/16 ISA adapters diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/networking/tulip.txt linux/Documentation/networking/tulip.txt --- v2.4.0-test5/linux/Documentation/networking/tulip.txt Thu Jul 27 17:37:59 2000 +++ linux/Documentation/networking/tulip.txt Fri Jul 28 12:50:52 2000 @@ -170,7 +170,7 @@ 0.9.4.3 (April 14, 2000): * mod_timer fix (Hal Murray) -* PNIC2 resusitation (Chris Smith) +* PNIC2 resuscitation (Chris Smith) 0.9.4.2 (March 21, 2000): * Fix 21041 CSR7, CSR13/14/15 handling diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/networking/vortex.txt linux/Documentation/networking/vortex.txt --- v2.4.0-test5/linux/Documentation/networking/vortex.txt Fri Jun 23 21:55:06 2000 +++ linux/Documentation/networking/vortex.txt Fri Jul 28 12:50:52 2000 @@ -8,7 +8,7 @@ The driver was written by Donald Becker -Don is no longer the prime maintener of this version of the driver. +Don is no longer the prime maintainer of this version of the driver. Please report problems to one or more of: Andrew Morton @@ -64,7 +64,7 @@ options 3c59x debug=3 rx_copybreak=300 -If you are using the PCMCIA tools (cardmgr) then theoptions may be +If you are using the PCMCIA tools (cardmgr) then the options may be placed in /etc/pcmcia/config.opts: module "3c59x" opts "debug=3 extra_reset=1" @@ -135,7 +135,7 @@ max_interrupt_work=N The driver's interrupt service routine can handle many receive and - transmit packets in a single invokation. It does this in a loop. + transmit packets in a single invocation. It does this in a loop. The value of max_interrupt_work governs how mnay times the interrupt service routine will loop. The default value is 32 loops. If this is exceeded the interrupt service routine gives up and generates a diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/networking/wan-router.txt linux/Documentation/networking/wan-router.txt --- v2.4.0-test5/linux/Documentation/networking/wan-router.txt Fri Jan 28 15:09:06 2000 +++ linux/Documentation/networking/wan-router.txt Fri Jul 28 12:50:52 2000 @@ -142,11 +142,11 @@ 2.0.8 Nov 02, 1999 - Fixed up the X25API code. - Clear call bug fixed.i - - Eanbled driver for multi-card + - Enabled driver for multi-card operation. 2.0.7 Aug 26, 1999 - Merged X25API code into WANPIPE. - - Fixed a memeory leak for X25API + - Fixed a memory leak for X25API - Updated the X25API code for 2.2.X kernels. - Improved NEM handling. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/networking/wanpipe.txt linux/Documentation/networking/wanpipe.txt --- v2.4.0-test5/linux/Documentation/networking/wanpipe.txt Fri Jan 28 15:09:06 2000 +++ linux/Documentation/networking/wanpipe.txt Fri Jul 28 12:50:52 2000 @@ -228,7 +228,7 @@ creating applications using BiSync streaming. -2.0.5 Aug 04, 1999 CHDLC initializatin bug fix. +2.0.5 Aug 04, 1999 CHDLC initialization bug fix. PPP interrupt driven driver: Fix to the PPP line hangup problem. New PPP firmware @@ -241,13 +241,13 @@ Streaming HDLC API has been taken out. Available as a patch. -2.0.6 Aug 17, 1999 Increased debugging in statup scripts - Fixed insallation bugs from 2.0.5 +2.0.6 Aug 17, 1999 Increased debugging in startup scripts + Fixed installation bugs from 2.0.5 Kernel patch works for both 2.2.10 and 2.2.11 kernels. There is no functional difference between the two packages 2.0.7 Aug 26, 1999 o Merged X25API code into WANPIPE. - o Fixed a memeory leak for X25API + o Fixed a memory leak for X25API o Updated the X25API code for 2.2.X kernels. o Improved NEM handling. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/networking/wavelan.txt linux/Documentation/networking/wavelan.txt --- v2.4.0-test5/linux/Documentation/networking/wavelan.txt Sat Feb 26 22:31:37 2000 +++ linux/Documentation/networking/wavelan.txt Fri Jul 28 12:50:52 2000 @@ -19,7 +19,7 @@ This is the driver for the ISA version of the first generation of the Wavelan, now discontinued. The device is 2 Mb/s, composed of a -Intel 82586 controler and a Lucent Modem, and is NOT 802.11 compliant. +Intel 82586 controller and a Lucent Modem, and is NOT 802.11 compliant. The driver has been tested with the following hardware : o Wavelan ISA 915 MHz (full length ISA card) o Wavelan ISA 915 MHz 2.0 (half length ISA card) @@ -38,7 +38,7 @@ This is the driver for the PCMCIA version of the first generation of the Wavelan, now discontinued. The device is 2 Mb/s, -composed of a Intel 82593 controler (totally different from the 82586) +composed of a Intel 82593 controller (totally different from the 82586) and a Lucent Modem, and NOT 802.11 compatible. The driver has been tested with the following hardware : o Wavelan Pcmcia 915 MHz 2.0 (Pcmcia card + separate diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/nmi_watchdog.txt linux/Documentation/nmi_watchdog.txt --- v2.4.0-test5/linux/Documentation/nmi_watchdog.txt Sat Oct 9 11:47:50 1999 +++ linux/Documentation/nmi_watchdog.txt Fri Jul 28 12:50:52 2000 @@ -7,7 +7,7 @@ 'watchdog NMI interrupts'. (NMI: Non Maskable Interrupt - these get executed even if the system is otherwise locked up hard) This can be used to debug hard kernel lockups. By executing periodic NMI interrupts, -the kernel can monitor wether any CPU has locked up, and print out +the kernel can monitor whether any CPU has locked up, and print out debugging messages if so. You can enable/disable the NMI watchdog at boot time with the 'nmi_watchdog=1' boot parameter. Eg. the relevant lilo.conf entry: diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/powerpc/SBC8260_memory_mapping.txt linux/Documentation/powerpc/SBC8260_memory_mapping.txt --- v2.4.0-test5/linux/Documentation/powerpc/SBC8260_memory_mapping.txt Fri Jun 23 21:55:06 2000 +++ linux/Documentation/powerpc/SBC8260_memory_mapping.txt Fri Jul 28 12:50:52 2000 @@ -125,7 +125,7 @@ Although platform dependent, and certainly the case for embedded 8xx, traditionally memory is mapped at physical address zero, - and I/O devices above phsical address 0x80000000. The lowest + and I/O devices above physical address 0x80000000. The lowest and highest (above 0xf0000000) I/O addresses are traditionally used for devices or registers we need to map during kernel initialization and prior to KVM operation. For this reason, diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/s390/DASD linux/Documentation/s390/DASD --- v2.4.0-test5/linux/Documentation/s390/DASD Tue May 23 15:31:32 2000 +++ linux/Documentation/s390/DASD Fri Jul 28 12:50:52 2000 @@ -30,7 +30,7 @@ We currently implement one partition per volume, which is the whole volume, skipping the first blocks up to the volume label. These are reserved for IPL records and IBM's volume label to assure -accessability of the DASD from other OSs. In a later stage we will +accessibility of the DASD from other OSs. In a later stage we will provide support of partitions, maybe VTOC oriented or using a kind of partition table in the label record. @@ -38,7 +38,7 @@ -Low-level format (?CKD only) For using an ECKD-DASD as a Linux harddisk you have to low-level -format the tracks by issueing the BLKDASDFORMAT-ioctl on that +format the tracks by issuing the BLKDASDFORMAT-ioctl on that device. This will erase any data on that volume including IBM volume labels, VTOCs etc. The ioctl may take a 'struct format_data *' or 'NULL' as an argument. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/s390/cds.txt linux/Documentation/s390/cds.txt --- v2.4.0-test5/linux/Documentation/s390/cds.txt Fri May 12 14:18:55 2000 +++ linux/Documentation/s390/cds.txt Fri Jul 28 12:50:52 2000 @@ -778,7 +778,7 @@ The halt_IO() function returns : 0 - successful completion or request successfuly initiated --EBUSY - the device is currently performing a sysnchonous I/O +-EBUSY - the device is currently performing a synchronous I/O operation : do_IO() with flag DOIO_WAIT_FOR_INTERRUPT or an error was encountered and the device is currently be sensed diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/sound/CMI8338 linux/Documentation/sound/CMI8338 --- v2.4.0-test5/linux/Documentation/sound/CMI8338 Tue Dec 7 09:32:39 1999 +++ linux/Documentation/sound/CMI8338 Fri Jul 28 12:50:52 2000 @@ -14,7 +14,7 @@ 1. Support modem interface for 8738. (select in kernel configuration) 2. Enable S/PDIF-in to S/PDIF-out (S/PDIF loop). 3. Enable 4 channels analog duplicate mode on 3 jack or 4 jack - configurateion. + configuration. Be aware: C-Media Electronics Inc. is basically an IC design house, diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/sound/ESS linux/Documentation/sound/ESS --- v2.4.0-test5/linux/Documentation/sound/ESS Mon Feb 1 14:04:39 1999 +++ linux/Documentation/sound/ESS Fri Jul 28 12:50:52 2000 @@ -12,7 +12,7 @@ master volume control. Every chip that's detected as a ES1887 now has Full Duplex support. Made a -little testprogram that showes that is works, haven't seen a real program that +little testprogram that shows that is works, haven't seen a real program that needs this however. For ESS chips an additional parameter "esstype" can be specified. This controls diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/sound/Introduction linux/Documentation/sound/Introduction --- v2.4.0-test5/linux/Documentation/sound/Introduction Fri Mar 10 16:40:38 2000 +++ linux/Documentation/sound/Introduction Fri Jul 28 12:50:52 2000 @@ -320,7 +320,7 @@ 7) Turn on debug in drivers/sound/sound_config.h (DEB, DDB, MDB). -8) If the system reports insuffcient DMA memory then you may want to +8) If the system reports insufficient DMA memory then you may want to load sound with the "dmabufs=1" option. Or in /etc/conf.modules add preinstall sound dmabufs=1 @@ -354,7 +354,7 @@ When a sound card is first referenced and sound is modular the sound system will ask for the sound devices to be loaded. Initially it requests that -the driver for the sound system is loaded. It then wwill ask for +the driver for the sound system is loaded. It then will ask for sound-slot-0, where 0 is the first sound card. (sound-slot-1 the second and so on). Thus you can do diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/sound/Maestro linux/Documentation/sound/Maestro --- v2.4.0-test5/linux/Documentation/sound/Maestro Fri Jun 23 21:55:06 2000 +++ linux/Documentation/sound/Maestro Fri Jul 28 12:50:52 2000 @@ -70,7 +70,7 @@ As this is a PCI device, the module does not need to be informed of any IO or IRQ resources it should use, it devines these from the -system. Somtimes, on sucky PCs, the BIOS fails to allocated resources +system. Sometimes, on sucky PCs, the BIOS fails to allocated resources for the maestro. This will result in a message like: maestro: PCI subsystem reports IRQ 0, this might not be correct. from the kernel. Should this happen the sound chip most likely will diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/sound/PSS linux/Documentation/sound/PSS --- v2.4.0-test5/linux/Documentation/sound/PSS Fri Jan 21 18:19:15 2000 +++ linux/Documentation/sound/PSS Fri Jul 28 12:50:52 2000 @@ -3,7 +3,7 @@ device. The PSS driver enables MSS and MPU401 modes of the card. SB is not enabled since it doesn't work concurrently with MSS. -If you build this driver as a module then the driver takes the folowing +If you build this driver as a module then the driver takes the following parameters pss_io. The I/O base the PSS card is configured at (normally 0x220 diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/sound/README.OSS linux/Documentation/sound/README.OSS --- v2.4.0-test5/linux/Documentation/sound/README.OSS Fri Mar 10 16:40:38 2000 +++ linux/Documentation/sound/README.OSS Fri Jul 28 12:50:52 2000 @@ -81,7 +81,7 @@ Gregor Hoffleit Mozart support (initial version) Riccardo Facchetti Audio Excel DSP 16 (aedsp16) support James Hightower Spotting a tiny but important bug in CS423x support. - Denis Sablic OPTi 82C924 spesific enhancements (non PnP mode) + Denis Sablic OPTi 82C924 specific enhancements (non PnP mode) Tim MacKenzie Full duplex support for OPTi 82C930. Please look at lowlevel/README for more contributors. @@ -512,7 +512,7 @@ There are also chips called OPL3-SA2, OPL3-SA3, ..., OPL3SA-N. They are PnP chips and will not work with the OPL3-SA1 driver. You should - use the standard MSS, MPU401 and OPL3 options with thses chips and to + use the standard MSS, MPU401 and OPL3 options with these chips and to activate the card using isapnptools. 4Front Technologies SoftOSS @@ -1275,7 +1275,7 @@ NOTE! ESS cards are not compatible with MSS/WSS so don't worry if MSS support of OSS doesn't work with it. -There are some ES1688/688 based sound cards and (particularily) motherboards +There are some ES1688/688 based sound cards and (particularly) motherboards which use software configurable I/O port relocation feature of the chip. This ESS proprietary feature is supported only by OSS/Linux. @@ -1285,7 +1285,7 @@ work. ES1868 is a PnP chip which is (supposed to be) compatible with ESS1688 -brobably works with OSS/Free after initialization using isapnptools. +probably works with OSS/Free after initialization using isapnptools. Reveal cards ------------ diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/sound/README.modules linux/Documentation/sound/README.modules --- v2.4.0-test5/linux/Documentation/sound/README.modules Wed Apr 26 16:34:06 2000 +++ linux/Documentation/sound/README.modules Fri Jul 28 12:50:52 2000 @@ -77,7 +77,7 @@ The sound modules normally allocate DMA buffers during open() and deallocate them during close(). Linux can often have problems allocating DMA buffers for ISA cards on machines with more than 16MB RAM. This is -because ISA DMA buffers must exist below the 16MB boundry and it is quite +because ISA DMA buffers must exist below the 16MB boundary and it is quite possible that we can't find a large enough free block in this region after the machine has been running for any amount of time. The way to avoid this problem is to allocate the DMA buffers during module load and deallocate diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/sound/README.ymfsb linux/Documentation/sound/README.ymfsb --- v2.4.0-test5/linux/Documentation/sound/README.ymfsb Fri Jun 23 21:55:06 2000 +++ linux/Documentation/sound/README.ymfsb Fri Jul 28 12:50:52 2000 @@ -28,7 +28,7 @@ It can only play 22.05kHz / 8bit / Stereo samples, control external MIDI port. If you want to use your card as recent "16-bit" card, you should use - Alsa or OSS/Linux driver. Ofcource you can write native PCI driver for + Alsa or OSS/Linux driver. Of course you can write native PCI driver for your cards :) diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/stallion.txt linux/Documentation/stallion.txt --- v2.4.0-test5/linux/Documentation/stallion.txt Sun Mar 28 09:02:27 1999 +++ linux/Documentation/stallion.txt Fri Jul 28 12:50:52 2000 @@ -62,7 +62,7 @@ boards. There are two methods of configuring ISA, EISA and MCA boards into the drivers. -If using the driver as a loadable module then the simplist method is to pass +If using the driver as a loadable module then the simplest method is to pass the driver configuration as module arguments. The other method is to modify the driver source to add configuration lines for each board in use. @@ -108,7 +108,7 @@ where: - board? -- specifies the arbitary board number of this board, + board? -- specifies the arbitrary board number of this board, can be in the range 0 to 3. name -- textual name of this board. The board name is the comman diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/sysctl/vm.txt linux/Documentation/sysctl/vm.txt --- v2.4.0-test5/linux/Documentation/sysctl/vm.txt Mon Jul 5 20:04:47 1999 +++ linux/Documentation/sysctl/vm.txt Mon Aug 7 23:01:34 2000 @@ -118,11 +118,11 @@ reaches this number, only the kernel can allocate more memory. freepages.low If the number of free pages gets below this - point, the kernel starts swapping agressively. + point, the kernel starts swapping aggressively. freepages.high The kernel tries to keep up to this amount of memory free; if memory comes below this point, the kernel gently starts swapping in the hopes - that it never has to do real agressive swapping. + that it never has to do real aggressive swapping. ============================================================== @@ -168,7 +168,7 @@ This feature can be very useful because there are a lot of programs that malloc() huge amounts of memory "just-in-case" -and don't much of it. +and don't use much of it. Look at: mm/mmap.c::vm_enough_memory() for more information. @@ -198,7 +198,7 @@ - swap cache When your system is both deep in swap and high on cache, -it probably means that a lot of the swaped data is being +it probably means that a lot of the swapped data is being cached, making for more efficient swapping than possible with the 2.0 kernel. @@ -213,7 +213,7 @@ On a low-memory, single CPU system you can safely set these values to 0 so you don't waste the memory. On SMP systems it is used so that the system can do fast pagetable allocations -without having to aquire the kernel memory lock. +without having to acquire the kernel memory lock. For large systems, the settings are probably OK. For normal systems they won't hurt a bit. For small systems (<16MB ram) diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/sysrq.txt linux/Documentation/sysrq.txt --- v2.4.0-test5/linux/Documentation/sysrq.txt Fri Jun 23 21:55:06 2000 +++ linux/Documentation/sysrq.txt Fri Jul 28 12:50:52 2000 @@ -74,14 +74,14 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Well, un'R'aw is very handy when your X server or a svgalib program crashes. -sa'K' (Secure Access Key) is usefull when you want to be sure there are no +sa'K' (Secure Access Key) is useful when you want to be sure there are no trojan program is running at console and which could grab your password when you would try to login. It will kill all programs on given console and thus letting you make sure that the login prompt you see is actually the one from init, not some trojan program. IMPORTANT:In its true form it is not a true SAK like the one in :IMPORTANT IMPORTATN:c2 compliant systems, and it should be mistook as such. :IMPORTANT - It seems other find it usefull as (System Attention Key) which is + It seems other find it useful as (System Attention Key) which is useful when you want to exit a program that will not let you switch consoles. (For example, X or a svgalib program.) diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/usb/CREDITS linux/Documentation/usb/CREDITS --- v2.4.0-test5/linux/Documentation/usb/CREDITS Tue Apr 11 15:09:11 2000 +++ linux/Documentation/usb/CREDITS Fri Jul 28 12:50:52 2000 @@ -45,7 +45,7 @@ - USAR Systems provided us with one of their excellent USB Evaluation Kits. It allows us to test the Linux-USB driver - for compilance with the latest USB specification. USAR + for compliance with the latest USB specification. USAR Systems recognized the importance of an up-to-date open Operating System and supports this project with Hardware. Thanks!. @@ -64,9 +64,9 @@ Linux users. - Many thanks to ing büro h doran [http://www.ibhdoran.com]! - It was almost imposible to get a PC backplate USB connector + It was almost impossible to get a PC backplate USB connector for the motherboard here at Europe (mine, home-made, was - quite lowsy :). Now I know where to adquire nice USB stuff! + quite lousy :). Now I know where to acquire nice USB stuff! - Genius Germany donated a USB mouse to test the mouse boot protocol. They've also donated a F-23 digital joystick and a @@ -128,7 +128,7 @@ documentation for the UUSBD. Go for it! - Ric Klaren for doing nice - introductory documents (compiting with Alberto's :). + introductory documents (competing with Alberto's :). - Christian Groessler , for it's help on those itchy bits ... :) @@ -143,7 +143,7 @@ - Rasca Gmelch has revived the raw driver and pointed bugs, as well as started the uusbd-utils package. - - Peter Dettori is unconvering bugs like + - Peter Dettori is uncovering bugs like crazy, as well as making cool suggestions, great :) - All the Free Software and Linux community, the FSF & the GNU @@ -153,7 +153,7 @@ - Big thanks to Richard Stallman for creating Emacs! - The people at the linux-usb mailing list, for reading so - many messages :) Ok, no more kidding; for all your advices! + many messages :) Ok, no more kidding; for all your advises! - All the people at the USB Implementors Forum for their help and assistance. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/usb/URB.txt linux/Documentation/usb/URB.txt --- v2.4.0-test5/linux/Documentation/usb/URB.txt Thu Jan 6 12:57:47 2000 +++ linux/Documentation/usb/URB.txt Fri Jul 28 12:50:52 2000 @@ -23,7 +23,7 @@ - URBs can be linked. After completing one URB, the next one can be automatically submitted. This is especially useful for ISO transfers: You only have read/write the data from/to the buffers in the completion -handler, the continous streaming itself is transparently done by the +handler, the continuous streaming itself is transparently done by the URB-machinery. 1.2. The URB structure @@ -104,7 +104,7 @@ Usually, (to reduce restart time) the completion handler is called AFTER the URB re-submission. You can get the other way by setting -USB_URB_EARLY_COMPLETE in transfer_flags. This is implicite for +USB_URB_EARLY_COMPLETE in transfer_flags. This is implicit for INT transfers. 1.5. How to submit an URB? @@ -131,7 +131,7 @@ with the ASAP flag result in a seamless ISO streaming. Exception: The execution cannot be scheduled later than 900 frames from the 'now'-time. The same applies to INT transfers, but here the seamless continuation is -independent of the transfer flags (implicitely ASAP). +independent of the transfer flags (implicitly ASAP). 1.6. How to cancel an already running URB? @@ -174,14 +174,14 @@ audio synchronisation/adaptive transfer rates). You can also use the length 0 to omit one or more frames (striping). -As can be concluded from above, the UHCI-driver does not care for continous +As can be concluded from above, the UHCI-driver does not care for continuous data in case of short packet ISO reads! There's no fixup_isoc() like in the old driver. There may be a common routine to do this in the future, but this has nothing to do with the UHCI-driver! For scheduling you can choose your own start frame or ASAP. As written above, queuing more than one ISO frame with ASAP to the same device&endpoint result -in seamless ISO streaming. For continous streaming you have to use URB +in seamless ISO streaming. For continuous streaming you have to use URB linking. 1.9. How to start interrupt (INT) transfers? diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/usb/input.txt linux/Documentation/usb/input.txt --- v2.4.0-test5/linux/Documentation/usb/input.txt Fri Jun 23 21:55:06 2000 +++ linux/Documentation/usb/input.txt Fri Jul 28 12:50:52 2000 @@ -134,7 +134,7 @@ 3.1.3 usbkbd.c ~~~~~~~~~~~~~~ - Much like usbmouse.c, this module talks to keyboards with a simpplified + Much like usbmouse.c, this module talks to keyboards with a simplified HIDBP protocol. It's smaller, but doesn't support any extra special keys. Use hid.c instead if there isn't any special reason to use this. @@ -158,7 +158,7 @@ 3.2 Event handlers ~~~~~~~~~~~~~~~~~~ - Event handlers distrubite the events from the devices to userland and + Event handlers distribute the events from the devices to userland and kernel, as needed. 3.2.1 keybdev.c @@ -230,7 +230,7 @@ ~~~~~~~~~~~~~ Evdev is the generic input event interface. It passes the events generated in the kernel straight to the program, with timestamps. The API is still -evolving, but should be useable now. It's described in section 5. +evolving, but should be usable now. It's described in section 5. This should be the way for GPM and X to get keyboard and mouse mouse events. It allows for multihead in X without any specific multihead kernel @@ -273,7 +273,7 @@ You can test the joystick emulation with the 'jstest' utility, available in the joystick package (see Documentation/joystick.txt). - You can test the event devics with the 'evtest' utitily available on the + You can test the event devics with the 'evtest' utility available on the input driver homepage (see the URL above). 5. Event interface @@ -295,7 +295,7 @@ }; 'time' is the timestamp, it returns the time at which the event happened. -Type is for example EV_REL for relative momement, REL_KEY for a keypress or +Type is for example EV_REL for relative movement, REL_KEY for a keypress or release. More types are defined in include/linux/input.h. 'code' is event code, for example REL_X or KEY_BACKSPACE, again a complete diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/usb/ohci.txt linux/Documentation/usb/ohci.txt --- v2.4.0-test5/linux/Documentation/usb/ohci.txt Fri Jan 28 15:09:06 2000 +++ linux/Documentation/usb/ohci.txt Fri Jul 28 12:50:52 2000 @@ -1,7 +1,7 @@ The OHCI HCD layer is a simple but nearly complete implementation of what the USB people would call a HCD for the OHCI. - (ISO comming soon, Bulk, INT u. CTRL transfers enabled) + (ISO coming soon, Bulk, INT u. CTRL transfers enabled) It is based on Linus Torvalds UHCI code and Gregory Smith OHCI fragments (0.03 source tree). The layer (functions) on top of it, is for interfacing to the alternate-usb device-drivers. @@ -35,11 +35,11 @@ - Endpoint Descriptor (ED) handling more static approach (EDs should be allocated in parallel to the SET CONFIGURATION command and they live - as long as the function (device) is alive or another configuration is choosen. + as long as the function (device) is alive or another configuration is chosen. In the HCD layer the EDs has to be allocated manually either by calling a subroutine or by sending a USB root hub vendor specific command to the virtual root hub. At the alternate linux usb stack EDs will be added (allocated) at their first use. - ED will be unlinked from the HC chains if they are not bussy. + ED will be unlinked from the HC chains if they are not busy. files: ohci-hcd.c ohci-hcd.h routines: (do not use for drivers, use the top layer alternate usb commands instead) diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/usb/ov511.txt linux/Documentation/usb/ov511.txt --- v2.4.0-test5/linux/Documentation/usb/ov511.txt Thu Jul 27 17:37:59 2000 +++ linux/Documentation/usb/ov511.txt Fri Jul 28 12:50:52 2000 @@ -158,7 +158,7 @@ DEFAULT: 5 DESC: This is the number of times the driver will try to sync and detect the internal i2c bus (which connects the OV511 and sensor). If you are - getting intermittant detection failures ("Failed to read sensor ID...") + getting intermittent detection failures ("Failed to read sensor ID...") you should increase this by a modest amount. If setting it to 20 or so doesn't fix things, look elsewhere for the cause of the problem. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/usb/proc_usb_info.txt linux/Documentation/usb/proc_usb_info.txt --- v2.4.0-test5/linux/Documentation/usb/proc_usb_info.txt Tue Apr 11 15:09:11 2000 +++ linux/Documentation/usb/proc_usb_info.txt Fri Jul 28 12:50:52 2000 @@ -103,7 +103,7 @@ S: SerialNumber=ssss | |__Serial Number of this device as read from the device, | except that it is a generated string for USB host controllers -| (virtual root hubs), and represent's the host controller's +| (virtual root hubs), and represents the host controller's | unique identification in the system (currently I/O or | memory-mapped base address). |__String info tag diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/usb/scanner.txt linux/Documentation/usb/scanner.txt --- v2.4.0-test5/linux/Documentation/usb/scanner.txt Thu May 11 15:30:05 2000 +++ linux/Documentation/usb/scanner.txt Fri Jul 28 12:50:52 2000 @@ -121,11 +121,11 @@ MESSAGES -On occassion the message 'usb_control/bulk_msg: timeout' or something +On occasions the message 'usb_control/bulk_msg: timeout' or something similar will appear in '/var/adm/messages' or on the console or both, depending on how your system is configured. This is a side effect that scanners are sometimes very slow at warming up and/or -initialiazing. In most cases, however, only several of these messages +initializing. In most cases, however, only several of these messages should appear and is generally considered to be normal. If you see a message of the type 'excessive NAK's received' then this should be considered abnormal and generally indicates that the USB system is diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/usb/uhci.txt linux/Documentation/usb/uhci.txt --- v2.4.0-test5/linux/Documentation/usb/uhci.txt Thu Jan 6 12:57:47 2000 +++ linux/Documentation/usb/uhci.txt Fri Jul 28 12:50:52 2000 @@ -32,7 +32,7 @@ days (and nights) on the 16th and 17th of October 1999, now known as the great USB-October-Revolution started by GA, DF, and TS ;-) -Since the concept is in no way UHCI dependant, we hope that it will also be +Since the concept is in no way UHCI dependent, we hope that it will also be transfered to the OHCI-driver, so both drivers share a common API. 1.2. Advantages and disadvantages @@ -58,7 +58,7 @@ 1.4. What's really working? -As said above, CTRL und BULK already work fine even with the wrappers, +As said above, CTRL and BULK already work fine even with the wrappers, so legacy code wouldn't notice the change. Regarding to Thomas, ISO transfers now run stable with USB audio. INT transfers (e.g. mouse driver) work fine, too. @@ -113,7 +113,7 @@ affected, no atomic memory operation is required. The three QHs in the common chain are never equipped with TDs! -For ISO or INT, the TD for each frame is simply inserted into the apropriate +For ISO or INT, the TD for each frame is simply inserted into the appropriate ISO/INT-TD-chain for the desired frame. The 7 skeleton INT-TDs are scattered among the 1024 frames similar to the old UHCI driver. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/usb/usb-serial.txt linux/Documentation/usb/usb-serial.txt --- v2.4.0-test5/linux/Documentation/usb/usb-serial.txt Thu Jul 27 17:37:59 2000 +++ linux/Documentation/usb/usb-serial.txt Fri Jul 28 12:50:52 2000 @@ -46,7 +46,7 @@ Current status: The device's firmware is downloaded on connection, the new firmware - runs properly and all four ports are successfuly recognized and connected. + runs properly and all four ports are successfully recognized and connected. Data can be sent and received through the device on all ports. Hardware flow control needs to be implemented. diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/video4linux/CQcam.txt linux/Documentation/video4linux/CQcam.txt --- v2.4.0-test5/linux/Documentation/video4linux/CQcam.txt Tue Mar 14 19:10:38 2000 +++ linux/Documentation/video4linux/CQcam.txt Fri Jul 28 12:50:52 2000 @@ -127,7 +127,7 @@ The c-qcam is IEEE1284 compatible, so if you are using the proc file system (CONFIG_PROC_FS), the parallel printer support -(CONFIG_PRINTER), the IEEE 1284 sytem,(CONFIG_PRINTER_READBACK), you +(CONFIG_PRINTER), the IEEE 1284 system,(CONFIG_PRINTER_READBACK), you should be able to read some identification from your quickcam with modprobe -v parport diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/video4linux/README.cpia linux/Documentation/video4linux/README.cpia --- v2.4.0-test5/linux/Documentation/video4linux/README.cpia Wed Apr 26 16:34:06 2000 +++ linux/Documentation/video4linux/README.cpia Fri Jul 28 12:50:52 2000 @@ -107,7 +107,7 @@ device opens - complete control over camera via proc-interface (_all_ camera settings are supported), there is also a python-gtk application available for this [3] -- works under SMP (but the driver is completly serialized and synchronous) +- works under SMP (but the driver is completely serialized and synchronous) so you get no benefit from SMP, but at least it does not crash your box - might work for non-Intel architecture, let us know about this @@ -159,7 +159,7 @@ The camera can act in two modes, streaming or grabbing. Right now a polling grab-scheme is used. Maybe interrupt driven streaming will be -used for a ansychronous mmap interface in the next major release of the +used for a asynchronous mmap interface in the next major release of the driver. This might give a better frame rate. --------------------------------------------------------------------------- diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/video4linux/radiotrack.txt linux/Documentation/video4linux/radiotrack.txt --- v2.4.0-test5/linux/Documentation/video4linux/radiotrack.txt Fri Jan 7 19:13:21 2000 +++ linux/Documentation/video4linux/radiotrack.txt Fri Jul 28 12:50:52 2000 @@ -35,7 +35,7 @@ -------------------- The RadioTrack card is an ISA 8-bit FM radio card. The radio frequency (RF) input is simply an antenna lead, and the output is a power audio signal -available through a miniature phono plug. Its RF frequencies of operation are +available through a miniature phone plug. Its RF frequencies of operation are more or less limited from 87.0 to 109.0 MHz (the commercial FM broadcast band). Although the registers can be programmed to request frequencies beyond these limits, experiments did not give promising results. The variable diff -u --recursive --new-file v2.4.0-test5/linux/Documentation/video4linux/zr36120.txt linux/Documentation/video4linux/zr36120.txt --- v2.4.0-test5/linux/Documentation/video4linux/zr36120.txt Fri Jan 7 19:13:21 2000 +++ linux/Documentation/video4linux/zr36120.txt Fri Jul 28 12:50:52 2000 @@ -45,7 +45,7 @@ to memory is done in the so-called snapshot mode. In this mode the Zoran stops after capturing a frame worth of data and wait till the application set GRAB bit to indicate readiness for the -next frame. After detecting a set bit, the chip neetly waits +next frame. After detecting a set bit, the chip neatly waits till the start of a frame, captures it and it goes back to off. Smart ppl will notice the problem here. Its the waiting on the _next_ frame each time we set the GRAB bit... Oh well, 12,5 fps diff -u --recursive --new-file v2.4.0-test5/linux/MAINTAINERS linux/MAINTAINERS --- v2.4.0-test5/linux/MAINTAINERS Thu Jul 27 17:37:59 2000 +++ linux/MAINTAINERS Wed Aug 2 12:06:11 2000 @@ -393,8 +393,8 @@ S: Maintained FILE LOCKING (flock() and fcntl()/lockf()) -P: Andy Walker -M: andy@lysaker.kvaerner.no +P: Matthew Wilcox +M: willy@thepuffingroup.com L: linux-kernel@vger.rutgers.edu S: Maintained @@ -1142,7 +1142,7 @@ P: Matija Nalis M: Matija Nalis L: linux-kernel@vger.rutgers.edu -W: http://www.voyager.hr/~mnalis/umsdos/ +W: http://linux.voyager.hr/umsdos/ S: Maintained UNIFORM CDROM DRIVER diff -u --recursive --new-file v2.4.0-test5/linux/Makefile linux/Makefile --- v2.4.0-test5/linux/Makefile Thu Jul 27 17:37:59 2000 +++ linux/Makefile Fri Aug 4 11:23:37 2000 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 0 -EXTRAVERSION = -test5 +EXTRAVERSION = -test6 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) @@ -35,6 +35,7 @@ OBJDUMP = $(CROSS_COMPILE)objdump MAKEFILES = $(TOPDIR)/.config GENKSYMS = /sbin/genksyms +DEPMOD = /sbin/depmod MODFLAGS = -DMODULE CFLAGS_KERNEL = PERL = perl @@ -72,11 +73,14 @@ #export INSTALL_PATH=/boot # -# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory +# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory # relocations required by build roots. This is not defined in the # makefile but the arguement can be passed to make if needed. # +MODLIB := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE) +export MODLIB + # # standard CFLAGS # @@ -128,8 +132,8 @@ DRIVERS-m := DRIVERS- := -DRIVERS-$(CONFIG_DRM) += drivers/char/drm/drm.o DRIVERS-$(CONFIG_AGP) += drivers/char/agp/agp.o +DRIVERS-$(CONFIG_DRM) += drivers/char/drm/drm.o DRIVERS-$(CONFIG_NUBUS) += drivers/nubus/nubus.a DRIVERS-$(CONFIG_ISDN) += drivers/isdn/isdn.a DRIVERS-$(CONFIG_NET_FC) += drivers/net/fc/fc.a @@ -282,7 +286,7 @@ find include -type d \( -name "asm-*" -o -name config \) -prune -o -name '*.h' -print | xargs etags -a find $(SUBDIRS) init -name '*.c' | xargs etags -a -# Exuberant ctags works better with -I +# Exuberant ctags works better with -I tags: dummy CTAGSF=`ctags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__initlocaldata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_NOVERS"`; \ ctags $$CTAGSF `find include/asm-$(ARCH) -name '*.h'` && \ @@ -294,64 +298,49 @@ MODFLAGS += -DMODVERSIONS -include $(HPATH)/linux/modversions.h endif +.PHONY: modules modules: $(patsubst %, _mod_%, $(SUBDIRS)) -modules/MARKER: - mkdir -p modules - touch modules/MARKER - -$(patsubst %, _mod_%, $(SUBDIRS)) : include/linux/version.h include/config/MARKER modules/MARKER +.PHONY: $(patsubst %, _mod_%, $(SUBDIRS)) +$(patsubst %, _mod_%, $(SUBDIRS)) : include/linux/version.h include/config/MARKER $(MAKE) -C $(patsubst _mod_%, %, $@) CFLAGS="$(CFLAGS) $(MODFLAGS)" MAKING_MODULES=1 modules -modules_install: - @( \ - MODLIB=$(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE); \ - mkdir -p $$MODLIB; \ - rm -f $$MODLIB/build; \ - ln -s $TOPDIR $$MODLIB/build; \ - cd modules; \ - MODULES=""; \ - inst_mod() { These="`cat $$1`"; MODULES="$$MODULES $$These"; \ - mkdir -p $$MODLIB/$$2; cp $$These $$MODLIB/$$2; \ - echo Installing modules under $$MODLIB/$$2; \ - }; \ - \ - if [ -f BLOCK_MODULES ]; then inst_mod BLOCK_MODULES block; fi; \ - if [ -f NET_MODULES ]; then inst_mod NET_MODULES net; fi; \ - if [ -f IPV4_MODULES ]; then inst_mod IPV4_MODULES ipv4; fi; \ - if [ -f IPV6_MODULES ]; then inst_mod IPV6_MODULES ipv6; fi; \ - if [ -f ATM_MODULES ]; then inst_mod ATM_MODULES atm; fi; \ - if [ -f IDE_MODULES ]; then inst_mod IDE_MODULES ide; fi; \ - if [ -f SCSI_MODULES ]; then inst_mod SCSI_MODULES scsi; fi; \ - if [ -f FS_MODULES ]; then inst_mod FS_MODULES fs; fi; \ - if [ -f NLS_MODULES ]; then inst_mod NLS_MODULES fs; fi; \ - if [ -f CDROM_MODULES ]; then inst_mod CDROM_MODULES cdrom; fi; \ - if [ -f HAM_MODULES ]; then inst_mod HAM_MODULES net; fi; \ - if [ -f SOUND_MODULES ]; then inst_mod SOUND_MODULES sound; fi; \ - if [ -f VIDEO_MODULES ]; then inst_mod VIDEO_MODULES video; fi; \ - if [ -f FC4_MODULES ]; then inst_mod FC4_MODULES fc4; fi; \ - if [ -f IRDA_MODULES ]; then inst_mod IRDA_MODULES net; fi; \ - if [ -f SK98LIN_MODULES ]; then inst_mod SK98LIN_MODULES net; fi; \ - if [ -f SKFP_MODULES ]; then inst_mod SKFP_MODULES net; fi; \ - if [ -f USB_MODULES ]; then inst_mod USB_MODULES usb; fi; \ - if [ -f USB_STORAGE_MODULES ]; then inst_mod USB_STORAGE_MODULES usb; fi; \ - if [ -f USB_SERIAL_MODULES ]; then inst_mod USB_SERIAL_MODULES usb; fi; \ - if [ -f IEEE1394_MODULES ]; then inst_mod IEEE1394_MODULES ieee1394; fi; \ - if [ -f MTD_MODULES ]; then inst_mod MTD_MODULES mtd; fi; \ - if [ -f PCMCIA_MODULES ]; then inst_mod PCMCIA_MODULES pcmcia; fi; \ - if [ -f PCMCIA_NET_MODULES ]; then inst_mod PCMCIA_NET_MODULES pcmcia; fi; \ - if [ -f PCMCIA_CHAR_MODULES ]; then inst_mod PCMCIA_CHAR_MODULES pcmcia; fi; \ - if [ -f PCMCIA_SCSI_MODULES ]; then inst_mod PCMCIA_SCSI_MODULES pcmcia; fi; \ - \ - ls -1 -U *.o | sort > $$MODLIB/.allmods; \ - if [ -f $$MODLIB/net/3c59x.o ]; then \ - mkdir -p $$MODLIB/pcmcia; \ - ln -nfs ../net/3c59x.o $$MODLIB/pcmcia/3c575_cb.o; \ - MODULES="$$MODULES 3c575_cb.o"; fi; \ - echo $$MODULES | tr ' ' '\n' | sort | comm -23 $$MODLIB/.allmods - > $$MODLIB/.misc; \ - if [ -s $$MODLIB/.misc ]; then inst_mod $$MODLIB/.misc misc; fi; \ - rm -f $$MODLIB/.misc $$MODLIB/.allmods; \ - ) +.PHONY: modules_install +modules_install: _modinst_ $(patsubst %, _modinst_%, $(SUBDIRS)) _modinst_post + +.PHONY: _modinst_ +_modinst_: + @rm -rf $(MODLIB)/kernel + @rm -f $(MODLIB)/build + @mkdir -p $(MODLIB)/kernel + @ln -s $(TOPDIR) $(MODLIB)/build + +# If System.map exists, run depmod. This deliberately does not have a +# dependency on System.map since that would run the dependency tree on +# vmlinux. This depmod is only for convenience to give the initial +# boot a modules.dep even before / is mounted read-write. However the +# boot script depmod is the master version. +ifeq "$(strip $(INSTALL_MOD_PATH))" "" +depmod_opts := +else +depmod_opts := -b $(INSTALL_MOD_PATH) -r +endif +.PHONY: _modinst_post +_modinst_post: _modinst_post_pcmcia + if [ -r System.map ]; then $(DEPMOD) -ae -F System.map $(depmod_opts) $(KERNELRELEASE); fi + +# Backwards compatibilty symlinks for people still using old versions +# of pcmcia-cs with hard coded pathnames on insmod. Remove +# _modinst_post_pcmcia for kernel 2.4.1. +.PHONY: _modinst_post_pcmcia +_modinst_post_pcmcia: + cd $(MODLIB); \ + mkdir -p pcmcia; \ + find kernel -path '*/pcmcia/*' -name '*.o' | xargs -i -r ln -sf ../{} pcmcia + +.PHONY: $(patsubst %, _modinst_%, $(SUBDIRS)) +$(patsubst %, _modinst_%, $(SUBDIRS)) : + $(MAKE) -C $(patsubst _modinst_%, %, $@) modules_install # modules disabled.... diff -u --recursive --new-file v2.4.0-test5/linux/Rules.make linux/Rules.make --- v2.4.0-test5/linux/Rules.make Fri Jun 23 21:55:07 2000 +++ linux/Rules.make Fri Aug 4 11:23:37 2000 @@ -32,8 +32,6 @@ unexport MIX_OBJS unexport SYMTAB_OBJS -unexport MOD_LIST_NAME - # # Get things started. # @@ -132,37 +130,32 @@ PDWN=$(shell $(CONFIG_SHELL) $(TOPDIR)/scripts/pathdown.sh) endif -ifdef MOD_SUB_DIRS -$(patsubst %,_modsubdir_%,$(MOD_SUB_DIRS)) : dummy +unexport MOD_DIRS +MOD_DIRS := $(MOD_SUB_DIRS) $(MOD_IN_SUB_DIRS) +ifneq "$(strip $(MOD_DIRS))" "" +.PHONY: $(patsubst %,_modsubdir_%,$(MOD_DIRS)) +$(patsubst %,_modsubdir_%,$(MOD_DIRS)) : dummy $(MAKE) -C $(patsubst _modsubdir_%,%,$@) modules -endif -ifdef MOD_IN_SUB_DIRS -$(patsubst %,_modinsubdir_%,$(MOD_IN_SUB_DIRS)) : dummy - $(MAKE) -C $(patsubst _modinsubdir_%,%,$@) modules +.PHONY: $(patsubst %,_modinst_%,$(MOD_DIRS)) +$(patsubst %,_modinst_%,$(MOD_DIRS)) : dummy + $(MAKE) -C $(patsubst _modinst_%,%,$@) modules_install endif +.PHONY: modules modules: $(ALL_MOBJS) $(MIX_OBJS) $(MI_OBJS) dummy \ - $(patsubst %,_modsubdir_%,$(MOD_SUB_DIRS)) \ - $(patsubst %,_modinsubdir_%,$(MOD_IN_SUB_DIRS)) -ifneq "$(strip $(MOD_LIST_NAME))" "" - rm -f $$TOPDIR/modules/$(MOD_LIST_NAME) -ifdef MOD_SUB_DIRS - for i in $(MOD_SUB_DIRS); do \ - echo `basename $$i`.o >> $$TOPDIR/modules/$(MOD_LIST_NAME); done -endif -ifneq "$(strip $(ALL_MOBJS))" "" - echo $(ALL_MOBJS) >> $$TOPDIR/modules/$(MOD_LIST_NAME) -endif -ifneq "$(strip $(MOD_TO_LIST))" "" - echo $(MOD_TO_LIST) >> $$TOPDIR/modules/$(MOD_LIST_NAME) -endif -endif + $(patsubst %,_modsubdir_%,$(MOD_DIRS)) + +.PHONY: _modinst__ +_modinst__: dummy ifneq "$(strip $(ALL_MOBJS))" "" - echo $(PDWN) - cd $$TOPDIR/modules; for i in $(ALL_MOBJS); do \ - ln -sf ../$(PDWN)/$$i $$i; done + mkdir -p $(MODLIB)/kernel/$(PDWN) + cp $(ALL_MOBJS) $(MODLIB)/kernel/$(PDWN) endif + +.PHONY: modules_install +modules_install: _modinst__ \ + $(patsubst %,_modinst_%,$(MOD_DIRS)) # # A rule to do nothing diff -u --recursive --new-file v2.4.0-test5/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c --- v2.4.0-test5/linux/arch/alpha/kernel/alpha_ksyms.c Wed Apr 26 16:34:06 2000 +++ linux/arch/alpha/kernel/alpha_ksyms.c Fri Aug 4 16:15:38 2000 @@ -199,9 +199,6 @@ EXPORT_SYMBOL(write_lock); EXPORT_SYMBOL(read_lock); #endif -#else /* CONFIG_SMP */ -EXPORT_SYMBOL(__local_bh_count); -EXPORT_SYMBOL(__local_irq_count); #endif /* CONFIG_SMP */ EXPORT_SYMBOL(rtc_lock); diff -u --recursive --new-file v2.4.0-test5/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S --- v2.4.0-test5/linux/arch/alpha/kernel/entry.S Thu Jul 27 17:37:59 2000 +++ linux/arch/alpha/kernel/entry.S Fri Aug 4 16:15:38 2000 @@ -6,6 +6,7 @@ #include #include +#include #define SIGCHLD 20 @@ -576,10 +577,10 @@ ret_from_sys_call: cmovne $26,0,$19 /* $19 = 0 => non-restartable */ ldl $3,TASK_PROCESSOR($8) - lda $4,softirq_state - sll $3,5,$3 + lda $4,irq_stat /* softirq_active */ + sll $3,L1_CACHE_SHIFT,$3 addq $3,$4,$4 - ldq $4,0($4) + ldq $4,0($4) /* softirq_active[32] + softirq_mask[32] */ sll $4,32,$3 and $4,$3,$4 bne $4,handle_softirq diff -u --recursive --new-file v2.4.0-test5/linux/arch/alpha/kernel/irq_alpha.c linux/arch/alpha/kernel/irq_alpha.c --- v2.4.0-test5/linux/arch/alpha/kernel/irq_alpha.c Thu Jul 27 17:37:59 2000 +++ linux/arch/alpha/kernel/irq_alpha.c Fri Aug 4 16:15:38 2000 @@ -14,11 +14,7 @@ #include "proto.h" #include "irq_impl.h" -/* Only uniprocessor needs this IRQ/BH locking depth, on SMP it lives - in the per-cpu structure for cache reasons. */ #ifndef CONFIG_SMP -int __local_irq_count; -int __local_bh_count; unsigned long __irq_attempt[NR_IRQS]; #endif diff -u --recursive --new-file v2.4.0-test5/linux/arch/alpha/kernel/irq_smp.c linux/arch/alpha/kernel/irq_smp.c --- v2.4.0-test5/linux/arch/alpha/kernel/irq_smp.c Thu Mar 2 14:36:22 2000 +++ linux/arch/alpha/kernel/irq_smp.c Fri Aug 4 16:15:38 2000 @@ -40,13 +40,13 @@ printk("\n%s, CPU %d: %p\n", str, cpu, where); printk("irq: %d [%d %d]\n", irqs_running(), - cpu_data[0].irq_count, - cpu_data[1].irq_count); + local_irq_count(0), + local_irq_count(1)); printk("bh: %d [%d %d]\n", spin_is_locked(&global_bh_lock) ? 1 : 0, - cpu_data[0].bh_count, - cpu_data[1].bh_count); + local_bh_count(0), + local_bh_count(1)); #if 0 stack = (unsigned long *) &str; for (i = 40; i ; i--) { diff -u --recursive --new-file v2.4.0-test5/linux/arch/alpha/kernel/smp.c linux/arch/alpha/kernel/smp.c --- v2.4.0-test5/linux/arch/alpha/kernel/smp.c Thu Jul 27 17:37:59 2000 +++ linux/arch/alpha/kernel/smp.c Fri Aug 4 16:15:38 2000 @@ -108,8 +108,8 @@ cpu_data[cpuid].loops_per_sec = loops_per_sec; cpu_data[cpuid].last_asn = (cpuid << WIDTH_HARDWARE_ASN) + ASN_FIRST_VERSION; - cpu_data[cpuid].irq_count = 0; - cpu_data[cpuid].bh_count = 0; + local_irq_count(cpuid) = 0; + local_bh_count(cpuid) = 0; } /* diff -u --recursive --new-file v2.4.0-test5/linux/arch/alpha/mm/init.c linux/arch/alpha/mm/init.c --- v2.4.0-test5/linux/arch/alpha/mm/init.c Fri Jun 23 21:55:07 2000 +++ linux/arch/alpha/mm/init.c Mon Aug 7 21:02:27 2000 @@ -141,7 +141,7 @@ __bad_page(void) { memset((void *) EMPTY_PGE, 0, PAGE_SIZE); - return pte_mkdirty(mk_pte(mem_map + MAP_NR(EMPTY_PGE), PAGE_SHARED)); + return pte_mkdirty(mk_pte(virt_to_page(EMPTY_PGE), PAGE_SHARED)); } void @@ -325,8 +325,8 @@ addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { - ClearPageReserved(mem_map + MAP_NR(addr)); - set_page_count(mem_map+MAP_NR(addr), 1); + ClearPageReserved(virt_to_page(addr)); + set_page_count(virt_to_page(addr), 1); free_page(addr); totalram_pages++; } @@ -339,8 +339,8 @@ free_initrd_mem(unsigned long start, unsigned long end) { for (; start < end; start += PAGE_SIZE) { - ClearPageReserved(mem_map + MAP_NR(start)); - set_page_count(mem_map+MAP_NR(start), 1); + ClearPageReserved(virt_to_page(start)); + set_page_count(virt_to_page(start), 1); free_page(start); totalram_pages++; } diff -u --recursive --new-file v2.4.0-test5/linux/arch/arm/kernel/armksyms.c linux/arch/arm/kernel/armksyms.c --- v2.4.0-test5/linux/arch/arm/kernel/armksyms.c Thu Jul 27 17:37:59 2000 +++ linux/arch/arm/kernel/armksyms.c Fri Aug 4 16:15:37 2000 @@ -91,8 +91,6 @@ EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(dump_fpu); EXPORT_SYMBOL(udelay); -EXPORT_SYMBOL(local_bh_count); -EXPORT_SYMBOL(local_irq_count); #ifdef CONFIG_CPU_32 EXPORT_SYMBOL(__ioremap); EXPORT_SYMBOL(__iounmap); diff -u --recursive --new-file v2.4.0-test5/linux/arch/arm/kernel/entry-common.S linux/arch/arm/kernel/entry-common.S --- v2.4.0-test5/linux/arch/arm/kernel/entry-common.S Fri Jun 23 21:55:07 2000 +++ linux/arch/arm/kernel/entry-common.S Fri Aug 4 16:15:37 2000 @@ -9,7 +9,7 @@ #ifdef CONFIG_SMP #error SMP not supported #else - ldr \rd, __softirq_state + ldr \rd, __irq_stat #endif .endm @@ -22,7 +22,7 @@ add sp, sp, #S_OFF ret_from_sys_call: @ external entry get_softirq r0 - ldmia r0, {r0, r1} + ldmia r0, {r0, r1} @ softirq_active, softirq_mask mov r4, #1 @ flag this as being syscall return tst r0, r1 blne SYMBOL_NAME(do_softirq) @@ -48,7 +48,7 @@ .globl ret_from_exception ret_from_exception: @ external entry get_softirq r0 - ldmia r0, {r0, r1} + ldmia r0, {r0, r1} @ softirq_active, softirq_mask mov r4, #0 tst r0, r1 blne SYMBOL_NAME(do_softirq) @@ -129,9 +129,9 @@ b SYMBOL_NAME(deferred) .align 5 - .type __softirq_state, #object -__softirq_state: - .word SYMBOL_NAME(softirq_state) + .type __irq_stat, #object +__irq_stat: + .word SYMBOL_NAME(irq_stat) .type sys_call_table, #object ENTRY(sys_call_table) diff -u --recursive --new-file v2.4.0-test5/linux/arch/arm/kernel/irq.c linux/arch/arm/kernel/irq.c --- v2.4.0-test5/linux/arch/arm/kernel/irq.c Mon Jul 10 16:47:19 2000 +++ linux/arch/arm/kernel/irq.c Fri Aug 4 16:15:37 2000 @@ -46,8 +46,6 @@ */ #define MAX_IRQ_CNT 100000 -unsigned int local_bh_count[NR_CPUS]; -unsigned int local_irq_count[NR_CPUS]; spinlock_t irq_controller_lock; int setup_arm_irq(int, struct irqaction *); @@ -236,7 +234,7 @@ irq_exit(cpu, irq); - if (softirq_state[cpu].active & softirq_state[cpu].mask) + if (softirq_active(cpu) & softirq_mask(cpu)) do_softirq(); return; diff -u --recursive --new-file v2.4.0-test5/linux/arch/arm/mm/init.c linux/arch/arm/mm/init.c --- v2.4.0-test5/linux/arch/arm/mm/init.c Thu Jul 27 17:37:59 2000 +++ linux/arch/arm/mm/init.c Mon Aug 7 21:02:27 2000 @@ -534,8 +534,8 @@ memzero(zero_page, PAGE_SIZE); memzero(bad_page, PAGE_SIZE); - empty_zero_page = mem_map + MAP_NR(zero_page); - empty_bad_page = mem_map + MAP_NR(bad_page); + empty_zero_page = virt_to_page(zero_page); + empty_bad_page = virt_to_page(bad_page); empty_bad_pte_table = ((pte_t *)bad_table) + TABLE_OFFSET; } @@ -598,7 +598,7 @@ static inline void free_area(unsigned long addr, unsigned long end, char *s) { unsigned int size = (end - addr) >> 10; - struct page *page = mem_map + MAP_NR(addr); + struct page *page = virt_to_page(addr); for (; addr < end; addr += PAGE_SIZE, page ++) { ClearPageReserved(page); @@ -632,8 +632,8 @@ if (!keep_initrd) { for (addr = start; addr < end; addr += PAGE_SIZE) { - ClearPageReserved(mem_map + MAP_NR(addr)); - set_page_count(mem_map+MAP_NR(addr), 1); + ClearPageReserved(virt_to_page(addr)); + set_page_count(virt_to_page(addr), 1); free_page(addr); totalram_pages++; } diff -u --recursive --new-file v2.4.0-test5/linux/arch/arm/mm/mm-armv.c linux/arch/arm/mm/mm-armv.c --- v2.4.0-test5/linux/arch/arm/mm/mm-armv.c Mon Jul 10 16:47:19 2000 +++ linux/arch/arm/mm/mm-armv.c Mon Aug 7 21:02:27 2000 @@ -417,8 +417,8 @@ start = __phys_to_virt(start); end = __phys_to_virt(end); - pg = PAGE_ALIGN((unsigned long)(mem_map + MAP_NR(start))); - pgend = ((unsigned long)(mem_map + MAP_NR(end))) & PAGE_MASK; + pg = PAGE_ALIGN((unsigned long)(virt_to_page(start))); + pgend = ((unsigned long)(virt_to_page(end))) & PAGE_MASK; start = __virt_to_phys(pg); end = __virt_to_phys(pgend); diff -u --recursive --new-file v2.4.0-test5/linux/arch/arm/mm/small_page.c linux/arch/arm/mm/small_page.c --- v2.4.0-test5/linux/arch/arm/mm/small_page.c Tue Dec 7 09:32:40 1999 +++ linux/arch/arm/mm/small_page.c Mon Aug 7 21:02:27 2000 @@ -116,7 +116,7 @@ remove_page_from_queue(page); restore_flags(flags); - return page_address(page) + (offset << order->shift); + return (unsigned long) page_address(page) + (offset << order->shift); need_new_page: page = alloc_page(priority); @@ -142,12 +142,10 @@ static void __free_small_page(unsigned long spage, struct order *order) { unsigned long flags; - unsigned long nr; struct page *page; - nr = MAP_NR(spage); - if (nr < max_mapnr) { - page = mem_map + nr; + page = virt_to_page(spage); + if (VALID_PAGE(page)) { /* * The container-page must be marked Reserved diff -u --recursive --new-file v2.4.0-test5/linux/arch/i386/Makefile linux/arch/i386/Makefile --- v2.4.0-test5/linux/arch/i386/Makefile Fri Jul 14 12:12:05 2000 +++ linux/arch/i386/Makefile Mon Jul 31 10:20:47 2000 @@ -58,7 +58,7 @@ endif ifdef CONFIG_MK7 -CFLAGS += $(shell if $(CC) -march=i686 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=i686"; fi) -malign-functions=4 -fschedule-insns2 -mwide-multiply -fexpensive-optimizations +CFLAGS += $(shell if $(CC) -march=athlon -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=athlon"; else if $(CC) -march=i686 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=i686 -malign-functions=4"; fi fi) endif ifdef CONFIG_MCRUSOE diff -u --recursive --new-file v2.4.0-test5/linux/arch/i386/boot/compressed/misc.c linux/arch/i386/boot/compressed/misc.c --- v2.4.0-test5/linux/arch/i386/boot/compressed/misc.c Mon Jul 10 16:47:19 2000 +++ linux/arch/i386/boot/compressed/misc.c Mon Jul 31 10:48:17 2000 @@ -298,6 +298,7 @@ if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory.\n"); #endif output_data = (char *)0x100000; /* Points to 1M */ + free_mem_end_ptr = (long)real_mode; } struct moveparams { diff -u --recursive --new-file v2.4.0-test5/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v2.4.0-test5/linux/arch/i386/defconfig Thu Jul 27 17:37:59 2000 +++ linux/arch/i386/defconfig Mon Jul 31 21:50:03 2000 @@ -15,8 +15,8 @@ # Loadable module support # CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -# CONFIG_KMOD is not set +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y # # Processor type and features @@ -478,13 +478,13 @@ # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set +# CONFIG_AGP is not set CONFIG_DRM=y CONFIG_DRM_TDFX=y # CONFIG_DRM_GAMMA is not set # CONFIG_DRM_R128 is not set # CONFIG_DRM_I810 is not set # CONFIG_DRM_MGA is not set -# CONFIG_AGP is not set CONFIG_PCMCIA_SERIAL=y # diff -u --recursive --new-file v2.4.0-test5/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c --- v2.4.0-test5/linux/arch/i386/kernel/apm.c Thu Jul 27 17:37:59 2000 +++ linux/arch/i386/kernel/apm.c Wed Aug 9 14:21:14 2000 @@ -410,7 +410,7 @@ #ifndef CONFIG_APM_ALLOW_INTS # define APM_DO_CLI __cli() #else -# define APM_DO_CLI +# define APM_DO_CLI __sti() #endif #ifdef APM_ZERO_SEGS # define APM_DECL_SEGS \ diff -u --recursive --new-file v2.4.0-test5/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S --- v2.4.0-test5/linux/arch/i386/kernel/entry.S Mon Jul 10 16:47:19 2000 +++ linux/arch/i386/kernel/entry.S Sun Aug 6 22:21:23 2000 @@ -130,8 +130,8 @@ .previous #define GET_CURRENT(reg) \ - movl %esp, reg; \ - andl $-8192, reg; + movl $-8192, reg; \ + andl %esp, reg ENTRY(lcall7) pushfl # We get a different stack layout with call gates, @@ -206,11 +206,11 @@ #ifdef CONFIG_SMP movl processor(%ebx),%eax shll $5,%eax - movl SYMBOL_NAME(softirq_state)(,%eax),%ecx - testl SYMBOL_NAME(softirq_state)+4(,%eax),%ecx + movl SYMBOL_NAME(irq_stat)(,%eax),%ecx # softirq_active + testl SYMBOL_NAME(irq_stat)+4(,%eax),%ecx # softirq_mask #else - movl SYMBOL_NAME(softirq_state),%ecx - testl SYMBOL_NAME(softirq_state)+4,%ecx + movl SYMBOL_NAME(irq_stat),%ecx # softirq_active + testl SYMBOL_NAME(irq_stat)+4,%ecx # softirq_mask #endif jne handle_softirq @@ -262,11 +262,11 @@ GET_CURRENT(%ebx) movl processor(%ebx),%eax shll $5,%eax - movl SYMBOL_NAME(softirq_state)(,%eax),%ecx - testl SYMBOL_NAME(softirq_state)+4(,%eax),%ecx + movl SYMBOL_NAME(irq_stat)(,%eax),%ecx # softirq_active + testl SYMBOL_NAME(irq_stat)+4(,%eax),%ecx # softirq_mask #else - movl SYMBOL_NAME(softirq_state),%ecx - testl SYMBOL_NAME(softirq_state)+4,%ecx + movl SYMBOL_NAME(irq_stat),%ecx # softirq_active + testl SYMBOL_NAME(irq_stat)+4,%ecx # softirq_mask #endif jne handle_softirq diff -u --recursive --new-file v2.4.0-test5/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c --- v2.4.0-test5/linux/arch/i386/kernel/i386_ksyms.c Fri Jul 14 12:12:05 2000 +++ linux/arch/i386/kernel/i386_ksyms.c Tue Aug 8 12:35:36 2000 @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -24,6 +25,7 @@ #include #include #include +#include extern void dump_thread(struct pt_regs *, struct user *); extern spinlock_t rtc_lock; @@ -141,6 +143,15 @@ EXPORT_SYMBOL(get_wchan); -EXPORT_SYMBOL(irq_stat); - EXPORT_SYMBOL(rtc_lock); + +#undef memcpy +#undef memset +extern void * memset(void *,int,__kernel_size_t); +extern void * memcpy(void *,const void *,__kernel_size_t); +EXPORT_SYMBOL_NOVERS(memcpy); +EXPORT_SYMBOL_NOVERS(memset); + +#ifdef CONFIG_X86_PAE +EXPORT_SYMBOL(empty_zero_page); +#endif diff -u --recursive --new-file v2.4.0-test5/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c --- v2.4.0-test5/linux/arch/i386/kernel/io_apic.c Thu Jul 27 17:37:59 2000 +++ linux/arch/i386/kernel/io_apic.c Fri Aug 4 16:15:38 2000 @@ -1070,7 +1070,7 @@ for (j = 0; j < smp_num_cpus; j++) { cpu = cpu_logical_map(j); - if (nmi_counter(cpu) - tmp[cpu].__nmi_counter <= 3) { + if (nmi_count(cpu) - tmp[cpu].__nmi_count <= 3) { printk(KERN_WARNING "CPU#%d NMI appears to be stuck.\n", cpu); return 0; } diff -u --recursive --new-file v2.4.0-test5/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c --- v2.4.0-test5/linux/arch/i386/kernel/irq.c Thu Jul 27 17:37:59 2000 +++ linux/arch/i386/kernel/irq.c Fri Aug 4 16:15:38 2000 @@ -61,8 +61,6 @@ * interrupt controllers, without having to do assembly magic. */ -irq_cpustat_t irq_stat [NR_CPUS]; - /* * Controller mappings for all interrupt sources: */ @@ -160,7 +158,7 @@ p += sprintf(p, "NMI: "); for (j = 0; j < smp_num_cpus; j++) p += sprintf(p, "%10u ", - nmi_counter(cpu_logical_map(j))); + nmi_count(cpu_logical_map(j))); p += sprintf(p, "\n"); #if CONFIG_SMP p += sprintf(p, "LOC: "); @@ -536,7 +534,7 @@ desc->depth--; break; case 0: - printk("enable_irq() unbalanced from %p\n", + printk("enable_irq(%u) unbalanced from %p\n", irq, __builtin_return_address(0)); } spin_unlock_irqrestore(&desc->lock, flags); @@ -624,7 +622,7 @@ desc->handler->end(irq); spin_unlock(&desc->lock); - if (softirq_state[cpu].active & softirq_state[cpu].mask) + if (softirq_active(cpu) & softirq_mask(cpu)) do_softirq(); return 1; } @@ -775,6 +773,8 @@ * disabled. */ +static DECLARE_MUTEX(probe_sem); + /** * probe_irq_on - begin an interrupt autodetect * @@ -790,6 +790,7 @@ unsigned long val; unsigned long delay; + down(&probe_sem); /* * something may have generated an irq long ago and we want to * flush such a longstanding irq before considering it as spurious. @@ -868,15 +869,18 @@ * Scan the ISA bus interrupt lines and return a bitmap of * active interrupts. The interrupt probe logic state is then * returned to its previous value. + * + * Note: we need to scan all the irq's even though we will + * only return ISA irq numbers - just so that we reset them + * all to a known state. */ - unsigned int probe_irq_mask(unsigned long val) { int i; unsigned int mask; mask = 0; - for (i = 0; i < 16; i++) { + for (i = 0; i < NR_IRQS; i++) { irq_desc_t *desc = irq_desc + i; unsigned int status; @@ -884,7 +888,7 @@ status = desc->status; if (status & IRQ_AUTODETECT) { - if (!(status & IRQ_WAITING)) + if (i < 16 && !(status & IRQ_WAITING)) mask |= 1 << i; desc->status = status & ~IRQ_AUTODETECT; @@ -892,6 +896,7 @@ } spin_unlock_irq(&desc->lock); } + up(&probe_sem); return mask & val; } @@ -943,6 +948,7 @@ } spin_unlock_irq(&desc->lock); } + up(&probe_sem); if (nr_irqs > 1) irq_found = -irq_found; @@ -998,7 +1004,7 @@ if (!shared) { desc->depth = 0; - desc->status &= ~IRQ_DISABLED; + desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING); desc->handler->startup(irq); } spin_unlock_irqrestore(&desc->lock,flags); diff -u --recursive --new-file v2.4.0-test5/linux/arch/i386/kernel/microcode.c linux/arch/i386/kernel/microcode.c --- v2.4.0-test5/linux/arch/i386/kernel/microcode.c Fri Jul 14 12:12:05 2000 +++ linux/arch/i386/kernel/microcode.c Sun Aug 6 11:24:58 2000 @@ -1,13 +1,14 @@ /* - * CPU Microcode Update interface for Linux + * Intel CPU Microcode Update driver for Linux * * Copyright (C) 2000 Tigran Aivazian * * This driver allows to upgrade microcode on Intel processors - * belonging to P6 family - PentiumPro, Pentium II, Pentium III etc. + * belonging to P6 family - PentiumPro, Pentium II, + * Pentium III, Xeon etc. * * Reference: Section 8.10 of Volume III, Intel Pentium III Manual, - * Order Number 243192 or download from: + * Order Number 243192 or free download from: * * http://developer.intel.com/design/pentiumii/manuals/243192.htm * @@ -18,28 +19,31 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * 1.0 16 February 2000, Tigran Aivazian + * 1.0 16 Feb 2000, Tigran Aivazian * Initial release. - * 1.01 18 February 2000, Tigran Aivazian + * 1.01 18 Feb 2000, Tigran Aivazian * Added read() support + cleanups. - * 1.02 21 February 2000, Tigran Aivazian + * 1.02 21 Feb 2000, Tigran Aivazian * Added 'device trimming' support. open(O_WRONLY) zeroes * and frees the saved copy of applied microcode. - * 1.03 29 February 2000, Tigran Aivazian + * 1.03 29 Feb 2000, Tigran Aivazian * Made to use devfs (/dev/cpu/microcode) + cleanups. - * 1.04 06 June 2000, Simon Trimmer + * 1.04 06 Jun 2000, Simon Trimmer * Added misc device support (now uses both devfs and misc). * Added MICROCODE_IOCFREE ioctl to clear memory. - * 1.05 09 June 2000, Simon Trimmer + * 1.05 09 Jun 2000, Simon Trimmer * Messages for error cases (non intel & no suitable microcode). + * 1.06 03 Aug 2000, Tigran Aivazian + * Removed ->release(). Removed exclusive open and status bitmap. + * Added microcode_rwsem to serialize read()/write()/ioctl(). + * Removed global kernel lock usage. */ #include -#include #include #include +#include #include -#include #include #include @@ -47,7 +51,7 @@ #include #include -#define MICROCODE_VERSION "1.05" +#define MICROCODE_VERSION "1.06" MODULE_DESCRIPTION("Intel CPU (P6) microcode update driver"); MODULE_AUTHOR("Tigran Aivazian "); @@ -55,28 +59,20 @@ /* VFS interface */ static int microcode_open(struct inode *, struct file *); -static int microcode_release(struct inode *, struct file *); static ssize_t microcode_read(struct file *, char *, size_t, loff_t *); static ssize_t microcode_write(struct file *, const char *, size_t, loff_t *); static int microcode_ioctl(struct inode *, struct file *, unsigned int, unsigned long); - -/* internal helpers to do the work */ static int do_microcode_update(void); static void do_update_one(void *); -/* - * Bits in microcode_status. (31 bits of room for future expansion) - */ -#define MICROCODE_IS_OPEN 0 /* set if device is in use */ +/* read()/write()/ioctl() are serialized on this */ +DECLARE_RWSEM(microcode_rwsem); -static unsigned long microcode_status; - -/* the actual array of microcode blocks, each 2048 bytes */ -static struct microcode *microcode; -static unsigned int microcode_num; -static char *mc_applied; /* holds an array of applied microcode blocks */ -static unsigned int mc_fsize; +static struct microcode *microcode; /* array of 2048byte microcode blocks */ +static unsigned int microcode_num; /* number of chunks in microcode */ +static char *mc_applied; /* array of applied microcode blocks */ +static unsigned int mc_fsize; /* file size of /dev/cpu/microcode */ static struct file_operations microcode_fops = { owner: THIS_MODULE, @@ -84,7 +80,6 @@ write: microcode_write, ioctl: microcode_ioctl, open: microcode_open, - release: microcode_release, }; static struct miscdevice microcode_dev = { @@ -112,8 +107,7 @@ printk(KERN_ERR "microcode: failed to devfs_register()\n"); return -EINVAL; } - printk(KERN_INFO "P6 Microcode Update Driver v%s registered\n", - MICROCODE_VERSION); + printk(KERN_INFO "P6 Microcode Update Driver v%s\n", MICROCODE_VERSION); return 0; } @@ -130,30 +124,12 @@ module_init(microcode_init); module_exit(microcode_exit); -/* - * We enforce only one user at a time here with open/close. - */ -static int microcode_open(struct inode *inode, struct file *file) +static int microcode_open(struct inode *unused1, struct file *unused2) { - if (!capable(CAP_SYS_RAWIO)) - return -EPERM; - - /* one at a time, please */ - if (test_and_set_bit(MICROCODE_IS_OPEN, µcode_status)) - return -EBUSY; - - return 0; + return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; } -static int microcode_release(struct inode *inode, struct file *file) -{ - lock_kernel(); - clear_bit(MICROCODE_IS_OPEN, µcode_status); - unlock_kernel(); - return 0; -} - -/* a pointer to 'struct update_req' is passed to the IPI handler = do_update_one() +/* * update_req[cpu].err is set to 1 if update failed on 'cpu', 0 otherwise * if err==0, microcode[update_req[cpu].slot] points to applied block of microcode */ @@ -167,9 +143,11 @@ int i, error = 0, err; struct microcode *m; - if (smp_call_function(do_update_one, (void *)update_req, 1, 1) != 0) - panic("do_microcode_update(): timed out waiting for other CPUs\n"); - do_update_one((void *)update_req); + if (smp_call_function(do_update_one, NULL, 1, 1) != 0) { + printk(KERN_ERR "microcode: IPI timeout, giving up\n"); + return -EIO; + } + do_update_one(NULL); for (i=0; ierr = 1; /* be pessimistic */ + req->err = 1; /* assume the worst */ if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6){ - printk(KERN_ERR "microcode: CPU%d not an Intel P6\n", cpu_num ); + printk(KERN_ERR "microcode: CPU%d not an Intel P6\n", cpu_num); return; } @@ -243,18 +221,23 @@ } if(!found) - printk(KERN_ERR "microcode: found no data for CPU%d (sig=%x, pflags=%d)\n", cpu_num, sig, pf); + printk(KERN_ERR "microcode: CPU%d no microcode found! (sig=%x, pflags=%d)\n", + cpu_num, sig, pf); } static ssize_t microcode_read(struct file *file, char *buf, size_t len, loff_t *ppos) { if (*ppos >= mc_fsize) return 0; + down_read(µcode_rwsem); if (*ppos + len > mc_fsize) len = mc_fsize - *ppos; - if (copy_to_user(buf, mc_applied + *ppos, len)) + if (copy_to_user(buf, mc_applied + *ppos, len)) { + up_read(µcode_rwsem); return -EFAULT; + } *ppos += len; + up_read(µcode_rwsem); return len; } @@ -267,27 +250,29 @@ sizeof(struct microcode)); return -EINVAL; } + down_write(µcode_rwsem); if (!mc_applied) { mc_applied = kmalloc(smp_num_cpus*sizeof(struct microcode), GFP_KERNEL); if (!mc_applied) { printk(KERN_ERR "microcode: out of memory for saved microcode\n"); + up_write(µcode_rwsem); return -ENOMEM; } - memset(mc_applied, 0, mc_fsize); } - lock_kernel(); microcode_num = len/sizeof(struct microcode); microcode = vmalloc(len); if (!microcode) { ret = -ENOMEM; goto out_unlock; } + if (copy_from_user(microcode, buf, len)) { ret = -EFAULT; goto out_fsize; } + if(do_microcode_update()) { ret = -EIO; goto out_fsize; @@ -299,7 +284,7 @@ devfs_set_file_size(devfs_handle, mc_fsize); vfree(microcode); out_unlock: - unlock_kernel(); + up_write(µcode_rwsem); return ret; } @@ -308,23 +293,22 @@ { switch(cmd) { case MICROCODE_IOCFREE: + down_write(µcode_rwsem); if (mc_applied) { devfs_set_file_size(devfs_handle, 0); - memset(mc_applied, 0, mc_fsize); kfree(mc_applied); mc_applied = NULL; - printk(KERN_WARNING - "microcode: freed %d bytes\n", mc_fsize); + printk(KERN_INFO "microcode: freed %d bytes\n", mc_fsize); mc_fsize = 0; + up_write(µcode_rwsem); return 0; } + up_write(µcode_rwsem); return -ENODATA; default: - printk(KERN_ERR "microcode: unknown ioctl cmd=%d\n", - cmd); + printk(KERN_ERR "microcode: unknown ioctl cmd=%d\n", cmd); return -EINVAL; } - /* NOT REACHED */ return -EINVAL; } diff -u --recursive --new-file v2.4.0-test5/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c --- v2.4.0-test5/linux/arch/i386/kernel/traps.c Thu Jul 27 17:37:59 2000 +++ linux/arch/i386/kernel/traps.c Fri Aug 4 16:15:38 2000 @@ -459,7 +459,7 @@ unsigned char reason = inb(0x61); - ++nmi_counter(smp_processor_id()); + ++nmi_count(smp_processor_id()); if (!(reason & 0xc0)) { #if CONFIG_X86_IO_APIC /* diff -u --recursive --new-file v2.4.0-test5/linux/arch/i386/lib/Makefile linux/arch/i386/lib/Makefile --- v2.4.0-test5/linux/arch/i386/lib/Makefile Thu Jul 27 17:37:59 2000 +++ linux/arch/i386/lib/Makefile Tue Aug 8 09:31:00 2000 @@ -7,7 +7,8 @@ L_TARGET = lib.a L_OBJS = checksum.o old-checksum.o delay.o \ - usercopy.o getuser.o putuser.o iodebug.o + usercopy.o getuser.o putuser.o iodebug.o \ + memcpy.o ifdef CONFIG_X86_USE_3DNOW L_OBJS += mmx.o diff -u --recursive --new-file v2.4.0-test5/linux/arch/i386/lib/memcpy.c linux/arch/i386/lib/memcpy.c --- v2.4.0-test5/linux/arch/i386/lib/memcpy.c Wed Dec 31 16:00:00 1969 +++ linux/arch/i386/lib/memcpy.c Tue Aug 8 12:40:56 2000 @@ -0,0 +1,19 @@ +#include +#include + +#undef memcpy +#undef memset + +void * memcpy(void * to, const void * from, size_t n) +{ +#ifdef CONFIG_X86_USE_3DNOW + return __memcpy3d(to, from, n); +#else + return __memcpy(to, from, n); +#endif +} + +void * memset(void * s, int c, size_t count) +{ + return __memset(s, c, count); +} diff -u --recursive --new-file v2.4.0-test5/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c --- v2.4.0-test5/linux/arch/i386/mm/init.c Tue May 23 15:31:33 2000 +++ linux/arch/i386/mm/init.c Mon Aug 7 21:02:27 2000 @@ -566,8 +566,6 @@ #ifdef CONFIG_HIGHMEM highmem_start_page = mem_map + highstart_pfn; - /* cache the highmem_mapnr */ - highmem_mapnr = highstart_pfn; max_mapnr = num_physpages = highend_pfn; #else max_mapnr = num_physpages = max_low_pfn; @@ -642,8 +640,8 @@ addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { - ClearPageReserved(mem_map + MAP_NR(addr)); - set_page_count(mem_map+MAP_NR(addr), 1); + ClearPageReserved(virt_to_page(addr)); + set_page_count(virt_to_page(addr), 1); free_page(addr); totalram_pages++; } @@ -656,8 +654,8 @@ if (start < end) printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { - ClearPageReserved(mem_map + MAP_NR(start)); - set_page_count(mem_map+MAP_NR(start), 1); + ClearPageReserved(virt_to_page(start)); + set_page_count(virt_to_page(start), 1); free_page(start); totalram_pages++; } diff -u --recursive --new-file v2.4.0-test5/linux/arch/i386/mm/ioremap.c linux/arch/i386/mm/ioremap.c --- v2.4.0-test5/linux/arch/i386/mm/ioremap.c Wed Dec 8 14:11:25 1999 +++ linux/arch/i386/mm/ioremap.c Mon Aug 7 21:02:27 2000 @@ -121,15 +121,14 @@ */ if (phys_addr < virt_to_phys(high_memory)) { char *t_addr, *t_end; - int i; + struct page *page; t_addr = __va(phys_addr); t_end = t_addr + (size - 1); - for(i = MAP_NR(t_addr); i < MAP_NR(t_end); i++) { - if(!PageReserved(mem_map + i)) + for(page = virt_to_page(t_addr); page < virt_to_page(t_end); page++) + if(!PageReserved(page)) return NULL; - } } /* diff -u --recursive --new-file v2.4.0-test5/linux/arch/ia64/ia32/binfmt_elf32.c linux/arch/ia64/ia32/binfmt_elf32.c --- v2.4.0-test5/linux/arch/ia64/ia32/binfmt_elf32.c Thu Jul 27 17:37:59 2000 +++ linux/arch/ia64/ia32/binfmt_elf32.c Mon Aug 7 21:02:27 2000 @@ -81,9 +81,9 @@ { int nr; - put_shared_page(current, mem_map + MAP_NR(ia32_gdt_table), IA32_PAGE_OFFSET); + put_shared_page(current, virt_to_page(ia32_gdt_table), IA32_PAGE_OFFSET); if (PAGE_SHIFT <= IA32_PAGE_SHIFT) - put_shared_page(current, mem_map + MAP_NR(ia32_tss), IA32_PAGE_OFFSET + PAGE_SIZE); + put_shared_page(current, virt_to_page(ia32_tss), IA32_PAGE_OFFSET + PAGE_SIZE); nr = smp_processor_id(); diff -u --recursive --new-file v2.4.0-test5/linux/arch/ia64/kernel/entry.S linux/arch/ia64/kernel/entry.S --- v2.4.0-test5/linux/arch/ia64/kernel/entry.S Thu Jul 27 17:37:59 2000 +++ linux/arch/ia64/kernel/entry.S Fri Aug 4 16:15:37 2000 @@ -506,7 +506,7 @@ PT_REGS_UNWIND_INFO(0) #ifdef CONFIG_SMP adds r2=IA64_TASK_PROCESSOR_OFFSET,r13 - movl r3=softirq_state + movl r3=irq_stat // softirq_active ;; ld4 r2=[r2] ;; @@ -514,10 +514,10 @@ ;; add r3=r2,r3 #else - movl r3=softirq_state + movl r3=irq_stat // softirq_active #endif ;; - ld8 r2=[r3] // r3 is guaranteed to be 8-byte aligned! + ld8 r2=[r3] // r3 (softirq_active+softirq_mask) is guaranteed to be 8-byte aligned! ;; shr r3=r2,32 ;; diff -u --recursive --new-file v2.4.0-test5/linux/arch/ia64/kernel/ia64_ksyms.c linux/arch/ia64/kernel/ia64_ksyms.c --- v2.4.0-test5/linux/arch/ia64/kernel/ia64_ksyms.c Fri Jun 23 21:55:07 2000 +++ linux/arch/ia64/kernel/ia64_ksyms.c Fri Aug 4 16:15:38 2000 @@ -32,10 +32,6 @@ EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); -#include -#include -EXPORT_SYMBOL(irq_stat); - #include EXPORT_SYMBOL(cpu_data); EXPORT_SYMBOL(kernel_thread); diff -u --recursive --new-file v2.4.0-test5/linux/arch/ia64/kernel/irq.c linux/arch/ia64/kernel/irq.c --- v2.4.0-test5/linux/arch/ia64/kernel/irq.c Thu Jul 27 17:37:59 2000 +++ linux/arch/ia64/kernel/irq.c Fri Aug 4 16:15:37 2000 @@ -60,8 +60,6 @@ * interrupt controllers, without having to do assembly magic. */ -irq_cpustat_t irq_stat [NR_CPUS]; - /* * Controller mappings for all interrupt sources: */ @@ -162,7 +160,7 @@ p += sprintf(p, "NMI: "); for (j = 0; j < smp_num_cpus; j++) p += sprintf(p, "%10u ", - nmi_counter(cpu_logical_map(j))); + nmi_count(cpu_logical_map(j))); p += sprintf(p, "\n"); #if defined(CONFIG_SMP) && defined(__i386__) p += sprintf(p, "LOC: "); diff -u --recursive --new-file v2.4.0-test5/linux/arch/ia64/mm/init.c linux/arch/ia64/mm/init.c --- v2.4.0-test5/linux/arch/ia64/mm/init.c Fri Jun 23 21:55:07 2000 +++ linux/arch/ia64/mm/init.c Mon Aug 7 21:02:27 2000 @@ -173,8 +173,8 @@ addr = (unsigned long) &__init_begin; for (; addr < (unsigned long) &__init_end; addr += PAGE_SIZE) { - clear_bit(PG_reserved, &mem_map[MAP_NR(addr)].flags); - set_page_count(&mem_map[MAP_NR(addr)], 1); + clear_bit(PG_reserved, &virt_to_page(addr)->flags); + set_page_count(virt_to_page(addr), 1); free_page(addr); ++totalram_pages; } @@ -188,8 +188,8 @@ if (start < end) printk ("Freeing initrd memory: %ldkB freed\n", (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { - clear_bit(PG_reserved, &mem_map[MAP_NR(start)].flags); - set_page_count(&mem_map[MAP_NR(start)], 1); + clear_bit(PG_reserved, &virt_to_page(start)->flags); + set_page_count(virt_to_page(start), 1); free_page(start); ++totalram_pages; } @@ -249,7 +249,7 @@ pte_t *pte; if (!PageReserved(page)) - printk("put_gate_page: gate page at 0x%lx not in reserved memory\n", + printk("put_gate_page: gate page at 0x%p not in reserved memory\n", page_address(page)); pgd = pgd_offset_k(address); /* note: this is NOT pgd_offset()! */ @@ -372,7 +372,7 @@ unsigned long *count = arg; struct page *pg; - for (pg = mem_map + MAP_NR(start); pg < mem_map + MAP_NR(end); ++pg) + for (pg = virt_to_page(start); pg < virt_to_page(end); ++pg) if (PageReserved(pg)) ++num_reserved; *count += num_reserved; @@ -409,7 +409,7 @@ datasize >> 10, initsize >> 10); /* install the gate page in the global page table: */ - put_gate_page(mem_map + MAP_NR(__start_gate_section), GATE_ADDR); + put_gate_page(virt_to_page(__start_gate_section), GATE_ADDR); #ifndef CONFIG_IA64_SOFTSDV_HACKS /* diff -u --recursive --new-file v2.4.0-test5/linux/arch/m68k/atari/ataints.c linux/arch/m68k/atari/ataints.c --- v2.4.0-test5/linux/arch/m68k/atari/ataints.c Tue Aug 31 17:29:12 1999 +++ linux/arch/m68k/atari/ataints.c Fri Aug 4 16:15:37 2000 @@ -168,7 +168,7 @@ void atari_slow_irq_##n##_dummy (void) { \ __asm__ (__ALIGN_STR "\n" \ SYMBOL_NAME_STR(atari_slow_irq_) #n "_handler:\t" \ -" addql #1,"SYMBOL_NAME_STR(local_irq_count)"\n" \ +" addql #1,"SYMBOL_NAME_STR(irq_stat)"+8\n" /* local_irq_count */ \ SAVE_ALL_INT "\n" \ GET_CURRENT(%%d0) "\n" \ " andb #~(1<<(%c3&7)),%a4:w\n" /* mask this interrupt */ \ @@ -274,7 +274,7 @@ SYMBOL_NAME_STR(atari_fast_irq_handler) ": orw #0x700,%%sr /* disable all interrupts */ "SYMBOL_NAME_STR(atari_prio_irq_handler) ":\t - addql #1,"SYMBOL_NAME_STR(local_irq_count)"\n" + addql #1,"SYMBOL_NAME_STR(irq_stat)"+8\n" /* local_irq_count */ SAVE_ALL_INT "\n" GET_CURRENT(%%d0) " /* get vector number from stack frame and convert to source */ diff -u --recursive --new-file v2.4.0-test5/linux/arch/m68k/atari/stram.c linux/arch/m68k/atari/stram.c --- v2.4.0-test5/linux/arch/m68k/atari/stram.c Wed Feb 16 17:03:51 2000 +++ linux/arch/m68k/atari/stram.c Mon Aug 7 21:02:27 2000 @@ -305,7 +305,7 @@ /* always reserve first page of ST-RAM, the first 2 kB are * supervisor-only! */ - set_bit( PG_reserved, &mem_map[MAP_NR(stram_start)].flags ); + set_bit( PG_reserved, &virt_to_page(stram_start)->flags ); #ifdef CONFIG_STRAM_SWAP if (!max_swap_size) { @@ -699,7 +699,7 @@ if (pte_page(pte) != page) return; if (0 /* isswap */) - mem_map[MAP_NR(pte_page(pte))].offset = page; + virt_to_page(pte_page(pte))->offset = page; else /* We will be removing the swap cache in a moment, so... */ set_pte(dir, pte_mkdirty(pte)); @@ -716,7 +716,7 @@ DPRINTK( "unswap_pte: replacing entry %08lx by new page %08lx", entry, page ); set_pte(dir, pte_mkdirty(__mk_pte(page,vma->vm_page_prot))); - atomic_inc(&mem_map[MAP_NR(page)].count); + atomic_inc(&virt_to_page(page)->count); ++vma->vm_mm->rss; } swap_free(entry); @@ -934,7 +934,7 @@ get a clean page and read the swap into it. */ page_map = read_swap_cache(entry); if (page_map) { - page = page_address(page_map); + page = (unsigned long) page_address(page_map); read_lock(&tasklist_lock); for_each_task(p) unswap_process(p->mm, entry, page @@ -1291,7 +1291,7 @@ /* reserve a range of pages in mem_map[] */ static void reserve_region( unsigned long addr, unsigned long end ) { - mem_map_t *mapp = &mem_map[MAP_NR(addr)]; + mem_map_t *mapp = virt_to_page(addr); for( ; addr < end; addr += PAGE_SIZE, ++mapp ) set_bit( PG_reserved, &mapp->flags ); diff -u --recursive --new-file v2.4.0-test5/linux/arch/m68k/kernel/entry.S linux/arch/m68k/kernel/entry.S --- v2.4.0-test5/linux/arch/m68k/kernel/entry.S Sun Feb 13 19:29:03 2000 +++ linux/arch/m68k/kernel/entry.S Fri Aug 4 16:15:37 2000 @@ -171,7 +171,7 @@ #if 0 #if CONFIG_AMIGA SYMBOL_NAME_LABEL(ami_inthandler) - addql #1,SYMBOL_NAME(local_irq_count) + addql #1,SYMBOL_NAME(irq_stat)+8 | local_irq_count SAVE_ALL_INT GET_CURRENT(%d0) @@ -203,7 +203,7 @@ SYMBOL_NAME_LABEL(inthandler) SAVE_ALL_INT GET_CURRENT(%d0) - addql #1,SYMBOL_NAME(local_irq_count) + addql #1,SYMBOL_NAME(irq_stat)+8 | local_irq_count | put exception # in d0 bfextu %sp@(PT_VECTOR){#4,#10},%d0 @@ -222,7 +222,7 @@ 3: addql #8,%sp | pop parameters off stack SYMBOL_NAME_LABEL(ret_from_interrupt) - subql #1,SYMBOL_NAME(local_irq_count) + subql #1,SYMBOL_NAME(irq_stat)+8 | local_irq_count jeq 1f 2: RESTORE_ALL @@ -236,8 +236,8 @@ #endif /* check if we need to do software interrupts */ - movel SYMBOL_NAME(softirq_state),%d0 - andl SYMBOL_NAME(softirq_state)+4,%d0 + movel SYMBOL_NAME(irq_stat),%d0 | softirq_active + andl SYMBOL_NAME(irq_stat)+4,%d0 | softirq_mask jeq SYMBOL_NAME(ret_from_exception) pea SYMBOL_NAME(ret_from_exception) diff -u --recursive --new-file v2.4.0-test5/linux/arch/m68k/kernel/ints.c linux/arch/m68k/kernel/ints.c --- v2.4.0-test5/linux/arch/m68k/kernel/ints.c Sun Aug 15 11:47:29 1999 +++ linux/arch/m68k/kernel/ints.c Fri Aug 4 16:15:37 2000 @@ -57,10 +57,6 @@ #define NUM_IRQ_NODES 100 static irq_node_t nodes[NUM_IRQ_NODES]; -unsigned int local_irq_count[NR_CPUS]; - -unsigned int local_bh_count[NR_CPUS]; - static void dummy_enable_irq(unsigned int irq); static void dummy_disable_irq(unsigned int irq); static int dummy_request_irq(unsigned int irq, diff -u --recursive --new-file v2.4.0-test5/linux/arch/m68k/kernel/m68k_ksyms.c linux/arch/m68k/kernel/m68k_ksyms.c --- v2.4.0-test5/linux/arch/m68k/kernel/m68k_ksyms.c Sun Feb 13 19:29:03 2000 +++ linux/arch/m68k/kernel/m68k_ksyms.c Fri Aug 4 16:15:37 2000 @@ -52,8 +52,6 @@ EXPORT_SYMBOL(strnlen); EXPORT_SYMBOL(strrchr); EXPORT_SYMBOL(strstr); -EXPORT_SYMBOL(local_irq_count); -EXPORT_SYMBOL(local_bh_count); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(kernel_thread); diff -u --recursive --new-file v2.4.0-test5/linux/arch/m68k/mm/init.c linux/arch/m68k/mm/init.c --- v2.4.0-test5/linux/arch/m68k/mm/init.c Thu Feb 10 17:11:04 2000 +++ linux/arch/m68k/mm/init.c Mon Aug 7 21:02:27 2000 @@ -153,10 +153,10 @@ #if 0 #ifndef CONFIG_SUN3 if (virt_to_phys ((void *)tmp) >= mach_max_dma_address) - clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags); + clear_bit(PG_DMA, &virt_to_page(tmp)->flags); #endif #endif - if (PageReserved(mem_map+MAP_NR(tmp))) { + if (PageReserved(virt_to_page(tmp))) { if (tmp >= (unsigned long)&_text && tmp < (unsigned long)&_etext) codepages++; @@ -168,7 +168,7 @@ continue; } #if 0 - set_page_count(mem_map+MAP_NR(tmp), 1); + set_page_count(virt_to_page(tmp), 1); #ifdef CONFIG_BLK_DEV_INITRD if (!initrd_start || (tmp < (initrd_start & PAGE_MASK) || tmp >= initrd_end)) @@ -202,8 +202,8 @@ void free_initrd_mem(unsigned long start, unsigned long end) { for (; start < end; start += PAGE_SIZE) { - ClearPageReserved(mem_map + MAP_NR(start)); - set_page_count(mem_map+MAP_NR(start), 1); + ClearPageReserved(virt_to_page(start)); + set_page_count(virt_to_page(start), 1); free_page(start); totalram_pages++; } diff -u --recursive --new-file v2.4.0-test5/linux/arch/m68k/mm/memory.c linux/arch/m68k/mm/memory.c --- v2.4.0-test5/linux/arch/m68k/mm/memory.c Fri Jan 28 15:09:07 2000 +++ linux/arch/m68k/mm/memory.c Mon Aug 7 21:02:27 2000 @@ -93,7 +93,7 @@ typedef struct list_head ptable_desc; static LIST_HEAD(ptable_list); -#define PD_PTABLE(page) ((ptable_desc *)&mem_map[MAP_NR(page)]) +#define PD_PTABLE(page) ((ptable_desc *)virt_to_page(page)) #define PD_PAGE(ptable) (list_entry(ptable, struct page, list)) #define PD_MARKBITS(dp) (*(unsigned char *)&PD_PAGE(dp)->index) diff -u --recursive --new-file v2.4.0-test5/linux/arch/m68k/mm/motorola.c linux/arch/m68k/mm/motorola.c --- v2.4.0-test5/linux/arch/m68k/mm/motorola.c Sun Feb 13 19:29:03 2000 +++ linux/arch/m68k/mm/motorola.c Mon Aug 7 21:02:27 2000 @@ -293,8 +293,8 @@ addr = (unsigned long)&__init_begin; for (; addr < (unsigned long)&__init_end; addr += PAGE_SIZE) { - mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved); - set_page_count(mem_map+MAP_NR(addr), 1); + virt_to_page(addr)->flags &= ~(1 << PG_reserved); + set_page_count(virt_to_page(addr), 1); free_page(addr); } } diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/Makefile linux/arch/mips/Makefile --- v2.4.0-test5/linux/arch/mips/Makefile Fri Jul 14 12:12:05 2000 +++ linux/arch/mips/Makefile Thu Jul 27 18:36:54 2000 @@ -50,25 +50,25 @@ CFLAGS := $(CFLAGS) -mcpu=r3000 -mips1 endif ifdef CONFIG_CPU_R6000 -CFLAGS := $(CFLAGS) -mcpu=r6000 -mips2 +CFLAGS := $(CFLAGS) -mcpu=r6000 -mips2 -Wa,--trap endif ifdef CONFIG_CPU_R4300 -CFLAGS := $(CFLAGS) -mcpu=r4300 -mips2 +CFLAGS := $(CFLAGS) -mcpu=r4300 -mips2 -Wa,--trap endif ifdef CONFIG_CPU_R4X00 -CFLAGS := $(CFLAGS) -mcpu=r4600 -mips2 +CFLAGS := $(CFLAGS) -mcpu=r4600 -mips2 -Wa,--trap endif ifdef CONFIG_CPU_R5000 -CFLAGS := $(CFLAGS) -mcpu=r8000 -mips2 +CFLAGS := $(CFLAGS) -mcpu=r8000 -mips2 -Wa,--trap endif ifdef CONFIG_CPU_NEVADA -CFLAGS := $(CFLAGS) -mcpu=r8000 -mips2 -mmad +CFLAGS := $(CFLAGS) -mcpu=r8000 -mips2 -Wa,--trap -mmad endif ifdef CONFIG_CPU_R8000 -CFLAGS := $(CFLAGS) -mcpu=r8000 -mips2 +CFLAGS := $(CFLAGS) -mcpu=r8000 -mips2 -Wa,--trap endif ifdef CONFIG_CPU_R10000 -CFLAGS := $(CFLAGS) -mcpu=r8000 -mips2 +CFLAGS := $(CFLAGS) -mcpu=r8000 -mips2 -Wa,--trap endif # diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/arc/memory.c linux/arch/mips/arc/memory.c --- v2.4.0-test5/linux/arch/mips/arc/memory.c Mon Jul 10 16:47:19 2000 +++ linux/arch/mips/arc/memory.c Mon Aug 7 21:02:27 2000 @@ -228,8 +228,8 @@ addr = PAGE_OFFSET + p->base; while (addr < p->base + p->size) { - ClearPageReserved(mem_map + MAP_NR(addr)); - set_page_count(mem_map + MAP_NR(addr), 1); + ClearPageReserved(virt_to_page(addr)); + set_page_count(virt_to_page(addr), 1); free_page(addr); addr += PAGE_SIZE; freed += PAGE_SIZE; diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/baget/irq.c linux/arch/mips/baget/irq.c --- v2.4.0-test5/linux/arch/mips/baget/irq.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/baget/irq.c Fri Aug 4 16:15:37 2000 @@ -29,7 +29,6 @@ #include -irq_cpustat_t irq_stat [NR_CPUS]; unsigned long spurious_count = 0; /* diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/config.in linux/arch/mips/config.in --- v2.4.0-test5/linux/arch/mips/config.in Fri Jul 14 12:12:05 2000 +++ linux/arch/mips/config.in Thu Jul 27 18:36:54 2000 @@ -10,15 +10,6 @@ endmenu mainmenu_option next_comment -comment 'Loadable module support' -bool 'Enable loadable module support' CONFIG_MODULES -if [ "$CONFIG_MODULES" = "y" ]; then - bool ' Set version information on all module symbols' CONFIG_MODVERSIONS - bool ' Kernel module loader' CONFIG_KMOD -fi -endmenu - -mainmenu_option next_comment comment 'Machine selection' if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then bool 'Support for Acer PICA 1 chipset' CONFIG_ACER_PICA_61 @@ -100,80 +91,88 @@ endmenu mainmenu_option next_comment - comment 'CPU selection' +comment 'Loadable module support' +bool 'Enable loadable module support' CONFIG_MODULES +if [ "$CONFIG_MODULES" = "y" ]; then + bool ' Set version information on all module symbols' CONFIG_MODVERSIONS + bool ' Kernel module loader' CONFIG_KMOD +fi +endmenu + +mainmenu_option next_comment +comment 'CPU selection' - choice 'CPU type' \ - "R3000 CONFIG_CPU_R3000 \ - R6000 CONFIG_CPU_R6000 \ - R4300 CONFIG_CPU_R4300 \ - R4x00 CONFIG_CPU_R4X00 \ - R5000 CONFIG_CPU_R5000 \ - R56x0 CONFIG_CPU_NEVADA \ - R8000 CONFIG_CPU_R8000 \ - R10000 CONFIG_CPU_R10000" R4x00 - - bool 'Override CPU Options' CONFIG_CPU_ADVANCED - - if [ "$CONFIG_CPU_ADVANCED" = "y" ]; then - bool ' ll/sc Instructions available' CONFIG_CPU_HAS_LLSC - bool ' Writeback Buffer available' CONFIG_CPU_HAS_WB - else - if [ "$CONFIG_CPU_R3000" = "y" ]; then - if [ "$CONFIG_DECSTATION" = "y" ]; then - define_bool CONFIG_CPU_HAS_LLSC n - define_bool CONFIG_CPU_HAS_WB y - else - define_bool CONFIG_CPU_HAS_LLSC n - define_bool CONFIG_CPU_HAS_WB n - fi - else - define_bool CONFIG_CPU_HAS_LLSC y - define_bool CONFIG_CPU_HAS_WB n - fi - fi +choice 'CPU type' \ + "R3000 CONFIG_CPU_R3000 \ + R6000 CONFIG_CPU_R6000 \ + R4300 CONFIG_CPU_R4300 \ + R4x00 CONFIG_CPU_R4X00 \ + R5000 CONFIG_CPU_R5000 \ + R56x0 CONFIG_CPU_NEVADA \ + R8000 CONFIG_CPU_R8000 \ + R10000 CONFIG_CPU_R10000" R4x00 + +bool 'Override CPU Options' CONFIG_CPU_ADVANCED + +if [ "$CONFIG_CPU_ADVANCED" = "y" ]; then + bool ' ll/sc Instructions available' CONFIG_CPU_HAS_LLSC + bool ' Writeback Buffer available' CONFIG_CPU_HAS_WB +else + if [ "$CONFIG_CPU_R3000" = "y" ]; then + if [ "$CONFIG_DECSTATION" = "y" ]; then + define_bool CONFIG_CPU_HAS_LLSC n + define_bool CONFIG_CPU_HAS_WB y + else + define_bool CONFIG_CPU_HAS_LLSC n + define_bool CONFIG_CPU_HAS_WB n + fi + else + define_bool CONFIG_CPU_HAS_LLSC y + define_bool CONFIG_CPU_HAS_WB n + fi +fi endmenu mainmenu_option next_comment comment 'General setup' +if [ "$CONFIG_DECSTATION" = "y" -o "$CONFIG_DDB5074" = "y" ]; then + define_bool CONFIG_CPU_LITTLE_ENDIAN y +else + bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN +fi + +if [ "$CONFIG_PROC_FS" = "y" ]; then + define_bool CONFIG_KCORE_ELF y +fi +define_bool CONFIG_ELF_KERNEL y + +if [ "$CONFIG_CPU_LITTLE_ENDIAN" = "n" ]; then + bool 'Include IRIX binary compatibility' CONFIG_BINFMT_IRIX + bool 'Include forward keyboard' CONFIG_FORWARD_KEYBOARD +fi + +define_bool CONFIG_BINFMT_AOUT n +define_bool CONFIG_BINFMT_ELF y +tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC - if [ "$CONFIG_DECSTATION" = "y" -o "$CONFIG_DDB5074" = "y" ]; then - define_bool CONFIG_CPU_LITTLE_ENDIAN y - else - bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN - fi - - if [ "$CONFIG_PROC_FS" = "y" ]; then - define_bool CONFIG_KCORE_ELF y - fi - define_bool CONFIG_ELF_KERNEL y - - if [ "$CONFIG_CPU_LITTLE_ENDIAN" = "n" ]; then - bool 'Include IRIX binary compatibility' CONFIG_BINFMT_IRIX - bool 'Include forward keyboard' CONFIG_FORWARD_KEYBOARD - fi - - define_bool CONFIG_BINFMT_AOUT n - define_bool CONFIG_BINFMT_ELF y - tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC - - bool 'Networking support' CONFIG_NET - - if [ "$CONFIG_PCI" = "y" ]; then - source drivers/pci/Config.in - fi - - bool 'System V IPC' CONFIG_SYSVIPC - bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT - bool 'Sysctl support' CONFIG_SYSCTL - - source drivers/parport/Config.in - - if [ "$CONFIG_DECSTATION" = "y" ]; then - bool 'TURBOchannel support' CONFIG_TC -# if [ "$CONFIG_TC" = "y" ]; then -# bool ' Access.Bus support' CONFIG_ACCESSBUS -# fi - fi +bool 'Networking support' CONFIG_NET + +if [ "$CONFIG_PCI" = "y" ]; then + source drivers/pci/Config.in +fi + +bool 'System V IPC' CONFIG_SYSVIPC +bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT +bool 'Sysctl support' CONFIG_SYSCTL + +source drivers/parport/Config.in + +if [ "$CONFIG_DECSTATION" = "y" ]; then + bool 'TURBOchannel support' CONFIG_TC +# if [ "$CONFIG_TC" = "y" ]; then +# bool ' Access.Bus support' CONFIG_ACCESSBUS +# fi +fi endmenu if [ "$CONFIG_ISA" = "y" ]; then @@ -196,24 +195,24 @@ if [ "$CONFIG_DECSTATION" != "y" -a \ "$CONFIG_SGI_IP22" != "y" ]; then - source drivers/telephony/Config.in + source drivers/telephony/Config.in fi if [ "$CONFIG_SGI_IP22" != "y" -a \ "$CONFIG_DECSTATION" != "y" ]; then - mainmenu_option next_comment - comment 'ATA/IDE/MFM/RLL support' + mainmenu_option next_comment + comment 'ATA/IDE/MFM/RLL support' - tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE + tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE - if [ "$CONFIG_IDE" != "n" ]; then + if [ "$CONFIG_IDE" != "n" ]; then source drivers/ide/Config.in - else + else define_bool CONFIG_BLK_DEV_IDE_MODES n define_bool CONFIG_BLK_DEV_HD n - fi - endmenu + fi + endmenu fi mainmenu_option next_comment @@ -228,7 +227,7 @@ if [ "$CONFIG_DECSTATION" != "y" -a \ "$CONFIG_SGI_IP22" != "y" ]; then - source drivers/i2o/Config.in + source drivers/i2o/Config.in fi if [ "$CONFIG_NET" = "y" ]; then @@ -336,7 +335,7 @@ if [ "$CONFIG_SGI_NEWPORT_CONSOLE" != "y" ]; then define_bool CONFIG_DUMMY_CONSOLE y else - define_bool CONFIG_FONT_8x16 y + define_bool CONFIG_FONT_8x16 y fi bool 'SGI PROM Console Support' CONFIG_SGI_PROM_CONSOLE fi diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/dec/irq.c linux/arch/mips/dec/irq.c --- v2.4.0-test5/linux/arch/mips/dec/irq.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/dec/irq.c Fri Aug 4 16:15:37 2000 @@ -31,10 +31,6 @@ extern volatile unsigned int *imr; /* address of the interrupt mask register */ extern decint_t dec_interrupt[NR_INTS]; -irq_cpustat_t irq_stat [NR_CPUS]; - -unsigned int local_bh_count[NR_CPUS]; -unsigned int local_irq_count[NR_CPUS]; unsigned long spurious_count = 0; static inline void mask_irq(unsigned int irq_nr) diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/dec/prom/memory.c linux/arch/mips/dec/prom/memory.c --- v2.4.0-test5/linux/arch/mips/dec/prom/memory.c Mon Jul 10 16:47:19 2000 +++ linux/arch/mips/dec/prom/memory.c Mon Aug 7 21:02:27 2000 @@ -149,8 +149,8 @@ addr = PAGE_SIZE; while (addr < end) { - ClearPageReserved(mem_map + MAP_NR(addr)); - set_page_count(mem_map + MAP_NR(addr), 1); + ClearPageReserved(virt_to_page(addr)); + set_page_count(virt_to_page(addr), 1); free_page(addr); addr += PAGE_SIZE; } diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/defconfig linux/arch/mips/defconfig --- v2.4.0-test5/linux/arch/mips/defconfig Fri Jul 14 12:12:05 2000 +++ linux/arch/mips/defconfig Thu Jul 27 18:36:54 2000 @@ -29,6 +29,13 @@ # CONFIG_PCI is not set # +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# # CPU selection # # CONFIG_CPU_R3000 is not set @@ -63,9 +70,6 @@ # Parallel port support # # CONFIG_PARPORT is not set -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y # CONFIG_PCMCIA is not set # diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/defconfig-cobalt linux/arch/mips/defconfig-cobalt --- v2.4.0-test5/linux/arch/mips/defconfig-cobalt Fri Jul 14 12:12:05 2000 +++ linux/arch/mips/defconfig-cobalt Thu Jul 27 18:36:54 2000 @@ -31,6 +31,13 @@ # CONFIG_ISA is not set # +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# # CPU selection # # CONFIG_CPU_R3000 is not set @@ -64,9 +71,6 @@ # Parallel port support # # CONFIG_PARPORT is not set -CONFIG_MODULES=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y # CONFIG_PCMCIA is not set # @@ -444,7 +448,6 @@ # # CONFIG_FTAPE is not set # CONFIG_DRM is not set -# CONFIG_DRM_TDFX is not set # CONFIG_AGP is not set # @@ -522,6 +525,7 @@ # # Native Language Support # +CONFIG_NLS_DEFAULT="iso8859-1" CONFIG_NLS_CODEPAGE_437=m CONFIG_NLS_CODEPAGE_737=m CONFIG_NLS_CODEPAGE_775=m @@ -538,6 +542,10 @@ CONFIG_NLS_CODEPAGE_866=m CONFIG_NLS_CODEPAGE_869=m CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_950=m CONFIG_NLS_ISO8859_1=m CONFIG_NLS_ISO8859_2=m CONFIG_NLS_ISO8859_3=m @@ -550,6 +558,7 @@ # CONFIG_NLS_ISO8859_14 is not set # CONFIG_NLS_ISO8859_15 is not set CONFIG_NLS_KOI8_R=m +CONFIG_NLS_UTF8=m # # Sound diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/defconfig-decstation linux/arch/mips/defconfig-decstation --- v2.4.0-test5/linux/arch/mips/defconfig-decstation Fri Jul 14 12:12:05 2000 +++ linux/arch/mips/defconfig-decstation Thu Jul 27 18:36:54 2000 @@ -26,6 +26,13 @@ # CONFIG_PCI is not set # +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# # CPU selection # CONFIG_CPU_R3000=y @@ -58,9 +65,6 @@ # Parallel port support # # CONFIG_PARPORT is not set -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y CONFIG_TC=y # CONFIG_PCMCIA is not set diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/defconfig-ip22 linux/arch/mips/defconfig-ip22 --- v2.4.0-test5/linux/arch/mips/defconfig-ip22 Fri Jul 14 12:12:05 2000 +++ linux/arch/mips/defconfig-ip22 Thu Jul 27 18:36:54 2000 @@ -29,6 +29,13 @@ # CONFIG_PCI is not set # +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# # CPU selection # # CONFIG_CPU_R3000 is not set @@ -63,9 +70,6 @@ # Parallel port support # # CONFIG_PARPORT is not set -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y # CONFIG_PCMCIA is not set # diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/defconfig-orion linux/arch/mips/defconfig-orion --- v2.4.0-test5/linux/arch/mips/defconfig-orion Fri Jul 14 12:12:05 2000 +++ linux/arch/mips/defconfig-orion Thu Jul 27 18:36:54 2000 @@ -26,6 +26,11 @@ # CONFIG_PCI is not set # +# Loadable module support +# +# CONFIG_MODULES is not set + +# # CPU selection # # CONFIG_CPU_R3000 is not set @@ -60,7 +65,6 @@ # Parallel port support # # CONFIG_PARPORT is not set -# CONFIG_MODULES is not set # CONFIG_PCMCIA is not set # @@ -199,7 +203,6 @@ # # CONFIG_FTAPE is not set # CONFIG_DRM is not set -# CONFIG_DRM_TDFX is not set # CONFIG_AGP is not set # diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/defconfig-rm200 linux/arch/mips/defconfig-rm200 --- v2.4.0-test5/linux/arch/mips/defconfig-rm200 Fri Jul 14 12:12:05 2000 +++ linux/arch/mips/defconfig-rm200 Thu Jul 27 18:36:54 2000 @@ -28,6 +28,13 @@ CONFIG_PC_KEYB=y # +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# # CPU selection # # CONFIG_CPU_R3000 is not set @@ -61,9 +68,6 @@ # Parallel port support # # CONFIG_PARPORT is not set -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y # # Plug and Play configuration @@ -215,7 +219,7 @@ # CONFIG_WATCHDOG is not set # CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set -# CONFIG_RTC is not set +CONFIG_RTC=y # # Video For Linux @@ -230,7 +234,6 @@ # # CONFIG_FTAPE is not set # CONFIG_DRM is not set -# CONFIG_DRM_TDFX is not set # CONFIG_AGP is not set # diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/kernel/entry.S linux/arch/mips/kernel/entry.S --- v2.4.0-test5/linux/arch/mips/kernel/entry.S Tue May 23 15:31:33 2000 +++ linux/arch/mips/kernel/entry.S Fri Aug 4 16:15:37 2000 @@ -43,8 +43,8 @@ EXPORT(ret_from_sys_call) EXPORT(ret_from_irq) .type ret_from_irq,@function - lw t0, softirq_state - lw t1, softirq_state+4 # unused delay slot + lw t0, irq_stat # softirq_active + lw t1, irq_stat+4 # softirq_mask. unused delay slot and t0, t1 bnez t0, handle_softirq diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/kernel/irq.c linux/arch/mips/kernel/irq.c --- v2.4.0-test5/linux/arch/mips/kernel/irq.c Fri Jul 14 12:12:05 2000 +++ linux/arch/mips/kernel/irq.c Fri Aug 4 16:15:37 2000 @@ -47,8 +47,6 @@ * interrupt controllers, without having to do assembly magic. */ -irq_cpustat_t irq_stat [NR_CPUS]; - /* * This contains the irq mask for both 8259A irq controllers, it's an * int so we can deal with the third PIC in some systems like the RM300. @@ -63,8 +61,6 @@ #define cached_21 (__byte(0,cached_irq_mask)) #define cached_A1 (__byte(1,cached_irq_mask)) -unsigned int local_bh_count[NR_CPUS]; -unsigned int local_irq_count[NR_CPUS]; unsigned long spurious_count = 0; /* @@ -228,7 +224,7 @@ } irq_exit(cpu); - if (softirq_state[cpu].active&softirq_state[cpu].mask) + if (softirq_active(cpu)&softirq_mask(cpu)) do_softirq(); /* unmasking and bottom half handling is done magically for us. */ diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/kernel/mips_ksyms.c linux/arch/mips/kernel/mips_ksyms.c --- v2.4.0-test5/linux/arch/mips/kernel/mips_ksyms.c Fri Jul 14 12:12:05 2000 +++ linux/arch/mips/kernel/mips_ksyms.c Fri Aug 4 16:15:37 2000 @@ -140,4 +140,3 @@ #endif EXPORT_SYMBOL(get_wchan); -EXPORT_SYMBOL(irq_stat); diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/kernel/scall_o32.S linux/arch/mips/kernel/scall_o32.S --- v2.4.0-test5/linux/arch/mips/kernel/scall_o32.S Mon Jul 10 16:47:19 2000 +++ linux/arch/mips/kernel/scall_o32.S Fri Aug 4 16:15:37 2000 @@ -1,10 +1,9 @@ -/* $Id: scall_o32.S,v 1.10 2000/02/23 00:41:00 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1997, 1998 by Ralf Baechle + * Copyright (C) 1997, 1998, 1999, 2000 by Ralf Baechle */ #include #include @@ -16,7 +15,7 @@ #include /* This duplicates the definition from */ -#define PF_TRACESYS 0x00000020 /* tracing system calls */ +#define PT_TRACESYS 0x00000002 /* tracing system calls */ /* This duplicates the definition from */ #define SIGILL 4 /* Illegal instruction (ANSI). */ @@ -50,8 +49,8 @@ stack_done: sw a3, PT_R26(sp) # save for syscall restart - lw t0, TASK_FLAGS($28) # syscall tracing enabled? - andi t0, PF_TRACESYS + lw t0, TASK_PTRACE($28) # syscall tracing enabled? + andi t0, PT_TRACESYS bnez t0, trace_a_syscall jalr t2 # Do The Real Thing (TM) @@ -66,8 +65,8 @@ 1: sw v0, PT_R2(sp) # result EXPORT(o32_ret_from_sys_call) - lw t0, softirq_state - lw t1, softirq_state+4 # unused delay slot + lw t0, irq_stat # softirq_active + lw t1, irq_stat+4 # softirq_mask. unused delay slot and t0, t1 bnez t0, o32_handle_softirq diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/mm/andes.c linux/arch/mips/mm/andes.c --- v2.4.0-test5/linux/arch/mips/mm/andes.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/mm/andes.c Thu Jul 27 18:36:54 2000 @@ -1,5 +1,4 @@ -/* $Id: andes.c,v 1.10 2000/02/13 20:52:05 harald Exp $ - * +/* * andes.c: MMU and cache operations for the R10000 (ANDES). * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/mm/init.c linux/arch/mips/mm/init.c --- v2.4.0-test5/linux/arch/mips/mm/init.c Mon Jul 10 16:47:19 2000 +++ linux/arch/mips/mm/init.c Mon Aug 7 21:02:27 2000 @@ -120,7 +120,8 @@ static inline unsigned long setup_zero_pages(void) { - unsigned long order, size, pg; + unsigned long order, size; + struct page *page; switch (mips_cputype) { case CPU_R4000SC: @@ -137,11 +138,11 @@ if (!empty_zero_page) panic("Oh boy, that early out of memory?"); - pg = MAP_NR(empty_zero_page); - while (pg < MAP_NR(empty_zero_page) + (1 << order)) { - set_bit(PG_reserved, &mem_map[pg].flags); - set_page_count(mem_map + pg, 0); - pg++; + page = virt_to_page(empty_zero_page); + while (page < virt_to_page(empty_zero_page + (PAGE_SIZE << order))) { + set_bit(PG_reserved, &page->flags); + set_page_count(page, 0); + page++; } size = PAGE_SIZE << order; @@ -309,8 +310,8 @@ void free_initrd_mem(unsigned long start, unsigned long end) { for (; start < end; start += PAGE_SIZE) { - ClearPageReserved(mem_map + MAP_NR(start)); - set_page_count(mem_map+MAP_NR(start), 1); + ClearPageReserved(virt_to_page(start)); + set_page_count(virt_to_page(start), 1); free_page(start); totalram_pages++; } @@ -329,8 +330,8 @@ addr = (unsigned long) &__init_begin; while (addr < (unsigned long) &__init_end) { - ClearPageReserved(mem_map + MAP_NR(addr)); - set_page_count(mem_map + MAP_NR(addr), 1); + ClearPageReserved(virt_to_page(addr)); + set_page_count(virt_to_page(addr), 1); free_page(addr); totalram_pages++; addr += PAGE_SIZE; diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/mm/r2300.c linux/arch/mips/mm/r2300.c --- v2.4.0-test5/linux/arch/mips/mm/r2300.c Mon Jul 10 16:47:19 2000 +++ linux/arch/mips/mm/r2300.c Thu Jul 27 18:36:54 2000 @@ -6,8 +6,6 @@ * with a lot of changes to make this thing work for R3000s * Copyright (C) 1998, 2000 Harald Koerfgen * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov - * - * $Id: r2300.c,v 1.16 2000/03/13 10:33:05 raiko Exp $ */ #include #include @@ -294,7 +292,7 @@ static void r3k_flush_cache_mm(struct mm_struct *mm) { - if(mm->context != 0) { + if (mm->context != 0) { #ifdef DEBUG_CACHE printk("cmm[%d]", (int)mm->context); @@ -309,7 +307,7 @@ { struct vm_area_struct *vma; - if(mm->context == 0) + if (mm->context == 0) return; start &= PAGE_MASK; @@ -317,15 +315,15 @@ printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); #endif vma = find_vma(mm, start); - if(vma) { - if(mm->context != current->mm->context) { + if (vma) { + if (mm->context != current->active_mm->context) { flush_cache_all(); } else { unsigned long flags, physpage; save_and_cli(flags); - while(start < end) { - if((physpage = get_phys_page(start, mm))) + while (start < end) { + if ((physpage = get_phys_page(start, mm))) r3k_flush_icache_range(physpage, PAGE_SIZE); start += PAGE_SIZE; @@ -340,7 +338,7 @@ { struct mm_struct *mm = vma->vm_mm; - if(mm->context == 0) + if (mm->context == 0) return; #ifdef DEBUG_CACHE @@ -349,7 +347,7 @@ if (vma->vm_flags & VM_EXEC) { unsigned long physpage; - if((physpage = get_phys_page(page, vma->vm_mm))) + if ((physpage = get_phys_page(page, vma->vm_mm))) r3k_flush_icache_range(physpage, PAGE_SIZE); } @@ -416,7 +414,7 @@ void flush_tlb_mm(struct mm_struct *mm) { - if(mm->context != 0) { + if (mm->context != 0) { unsigned long flags; #ifdef DEBUG_TLB @@ -542,7 +540,13 @@ pte_t *ptep; int idx, pid; - pid = (get_entryhi() & 0xfc0); + /* + * Handle debugger faulting in for debugee. + */ + if (current->active_mm != vma->vm_mm) + return; + + pid = get_entryhi() & 0xfc0; #ifdef DEBUG_TLB if((pid != (vma->vm_mm->context & 0xfc0)) || (vma->vm_mm->context == 0)) { diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/mm/r4xx0.c linux/arch/mips/mm/r4xx0.c --- v2.4.0-test5/linux/arch/mips/mm/r4xx0.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/mm/r4xx0.c Sun Aug 6 11:43:17 2000 @@ -1,5 +1,4 @@ -/* $Id: r4xx0.c,v 1.29 2000/02/24 00:12:40 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -7,7 +6,7 @@ * r4xx0.c: R4000 processor variant specific MMU/Cache routines. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * Copyright (C) 1997, 1998 Ralf Baechle ralf@gnu.org + * Copyright (C) 1997, 1998, 1999, 2000 Ralf Baechle ralf@gnu.org * * To do: * @@ -996,7 +995,7 @@ struct vm_area_struct *vma; unsigned long flags; - if(mm->context == 0) + if (mm->context == 0) return; start &= PAGE_MASK; @@ -1004,8 +1003,8 @@ printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); #endif vma = find_vma(mm, start); - if(vma) { - if(mm->context != current->mm->context) { + if (vma) { + if (mm->context != current->active_mm->context) { r4k_flush_cache_all_s16d16i16(); } else { pgd_t *pgd; @@ -1037,7 +1036,7 @@ struct vm_area_struct *vma; unsigned long flags; - if(mm->context == 0) + if (mm->context == 0) return; start &= PAGE_MASK; @@ -1045,8 +1044,8 @@ printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); #endif vma = find_vma(mm, start); - if(vma) { - if(mm->context != current->mm->context) { + if (vma) { + if (mm->context != current->active_mm->context) { r4k_flush_cache_all_s32d16i16(); } else { pgd_t *pgd; @@ -1077,7 +1076,7 @@ struct vm_area_struct *vma; unsigned long flags; - if(mm->context == 0) + if (mm->context == 0) return; start &= PAGE_MASK; @@ -1086,7 +1085,7 @@ #endif vma = find_vma(mm, start); if(vma) { - if(mm->context != current->mm->context) { + if (mm->context != current->active_mm->context) { r4k_flush_cache_all_s64d16i16(); } else { pgd_t *pgd; @@ -1117,7 +1116,7 @@ struct vm_area_struct *vma; unsigned long flags; - if(mm->context == 0) + if (mm->context == 0) return; start &= PAGE_MASK; @@ -1125,8 +1124,8 @@ printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); #endif vma = find_vma(mm, start); - if(vma) { - if(mm->context != current->mm->context) { + if (vma) { + if (mm->context != current->active_mm->context) { r4k_flush_cache_all_s128d16i16(); } else { pgd_t *pgd; @@ -1157,7 +1156,7 @@ struct vm_area_struct *vma; unsigned long flags; - if(mm->context == 0) + if (mm->context == 0) return; start &= PAGE_MASK; @@ -1165,8 +1164,8 @@ printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); #endif vma = find_vma(mm, start); - if(vma) { - if(mm->context != current->mm->context) { + if (vma) { + if (mm->context != current->active_mm->context) { r4k_flush_cache_all_s32d32i32(); } else { pgd_t *pgd; @@ -1197,7 +1196,7 @@ struct vm_area_struct *vma; unsigned long flags; - if(mm->context == 0) + if (mm->context == 0) return; start &= PAGE_MASK; @@ -1205,8 +1204,8 @@ printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); #endif vma = find_vma(mm, start); - if(vma) { - if(mm->context != current->mm->context) { + if (vma) { + if (mm->context != current->active_mm->context) { r4k_flush_cache_all_s64d32i32(); } else { pgd_t *pgd; @@ -1237,7 +1236,7 @@ struct vm_area_struct *vma; unsigned long flags; - if(mm->context == 0) + if (mm->context == 0) return; start &= PAGE_MASK; @@ -1245,8 +1244,8 @@ printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); #endif vma = find_vma(mm, start); - if(vma) { - if(mm->context != current->mm->context) { + if (vma) { + if (mm->context != current->active_mm->context) { r4k_flush_cache_all_s128d32i32(); } else { pgd_t *pgd; @@ -1274,7 +1273,7 @@ unsigned long start, unsigned long end) { - if(mm->context != 0) { + if (mm->context != 0) { unsigned long flags; #ifdef DEBUG_CACHE @@ -1290,7 +1289,7 @@ unsigned long start, unsigned long end) { - if(mm->context != 0) { + if (mm->context != 0) { unsigned long flags; #ifdef DEBUG_CACHE @@ -1309,7 +1308,7 @@ */ static void r4k_flush_cache_mm_s16d16i16(struct mm_struct *mm) { - if(mm->context != 0) { + if (mm->context != 0) { #ifdef DEBUG_CACHE printk("cmm[%d]", (int)mm->context); #endif @@ -1319,7 +1318,7 @@ static void r4k_flush_cache_mm_s32d16i16(struct mm_struct *mm) { - if(mm->context != 0) { + if (mm->context != 0) { #ifdef DEBUG_CACHE printk("cmm[%d]", (int)mm->context); #endif @@ -1329,7 +1328,7 @@ static void r4k_flush_cache_mm_s64d16i16(struct mm_struct *mm) { - if(mm->context != 0) { + if (mm->context != 0) { #ifdef DEBUG_CACHE printk("cmm[%d]", (int)mm->context); #endif @@ -1339,7 +1338,7 @@ static void r4k_flush_cache_mm_s128d16i16(struct mm_struct *mm) { - if(mm->context != 0) { + if (mm->context != 0) { #ifdef DEBUG_CACHE printk("cmm[%d]", (int)mm->context); #endif @@ -1349,7 +1348,7 @@ static void r4k_flush_cache_mm_s32d32i32(struct mm_struct *mm) { - if(mm->context != 0) { + if (mm->context != 0) { #ifdef DEBUG_CACHE printk("cmm[%d]", (int)mm->context); #endif @@ -1359,7 +1358,7 @@ static void r4k_flush_cache_mm_s64d32i32(struct mm_struct *mm) { - if(mm->context != 0) { + if (mm->context != 0) { #ifdef DEBUG_CACHE printk("cmm[%d]", (int)mm->context); #endif @@ -1369,7 +1368,7 @@ static void r4k_flush_cache_mm_s128d32i32(struct mm_struct *mm) { - if(mm->context != 0) { + if (mm->context != 0) { #ifdef DEBUG_CACHE printk("cmm[%d]", (int)mm->context); #endif @@ -1379,7 +1378,7 @@ static void r4k_flush_cache_mm_d16i16(struct mm_struct *mm) { - if(mm->context != 0) { + if (mm->context != 0) { #ifdef DEBUG_CACHE printk("cmm[%d]", (int)mm->context); #endif @@ -1389,7 +1388,7 @@ static void r4k_flush_cache_mm_d32i32(struct mm_struct *mm) { - if(mm->context != 0) { + if (mm->context != 0) { #ifdef DEBUG_CACHE printk("cmm[%d]", (int)mm->context); #endif @@ -1411,7 +1410,7 @@ * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ - if(mm->context == 0) + if (mm->context == 0) return; #ifdef DEBUG_CACHE @@ -1427,7 +1426,7 @@ * If the page isn't marked valid, the page cannot possibly be * in the cache. */ - if(!(pte_val(*ptep) & _PAGE_VALID)) + if (!(pte_val(*ptep) & _PAGE_VALID)) goto out; text = (vma->vm_flags & VM_EXEC); @@ -1436,7 +1435,7 @@ * for every cache flush operation. So we do indexed flushes * in that case, which doesn't overly flush the cache too much. */ - if(mm->context != current->mm->context) { + if (mm->context != current->active_mm->context) { /* Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. */ @@ -1465,7 +1464,7 @@ * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ - if(mm->context == 0) + if (mm->context == 0) return; #ifdef DEBUG_CACHE @@ -1480,7 +1479,7 @@ /* If the page isn't marked valid, the page cannot possibly be * in the cache. */ - if(!(pte_val(*ptep) & _PAGE_VALID)) + if (!(pte_val(*ptep) & _PAGE_VALID)) goto out; text = (vma->vm_flags & VM_EXEC); @@ -1489,7 +1488,7 @@ * for every cache flush operation. So we do indexed flushes * in that case, which doesn't overly flush the cache too much. */ - if(mm->context != current->mm->context) { + if (mm->context != current->active_mm->context) { /* Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. */ @@ -1518,7 +1517,7 @@ * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ - if(mm->context == 0) + if (mm->context == 0) return; #ifdef DEBUG_CACHE @@ -1533,7 +1532,7 @@ /* If the page isn't marked valid, the page cannot possibly be * in the cache. */ - if(!(pte_val(*ptep) & _PAGE_VALID)) + if (!(pte_val(*ptep) & _PAGE_VALID)) goto out; text = (vma->vm_flags & VM_EXEC); @@ -1543,7 +1542,7 @@ * for every cache flush operation. So we do indexed flushes * in that case, which doesn't overly flush the cache too much. */ - if(mm->context != current->mm->context) { + if (mm->context != current->active_mm->context) { /* Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. */ @@ -1572,7 +1571,7 @@ * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ - if(mm->context == 0) + if (mm->context == 0) return; #ifdef DEBUG_CACHE @@ -1588,7 +1587,7 @@ * If the page isn't marked valid, the page cannot possibly be * in the cache. */ - if(!(pte_val(*ptep) & _PAGE_VALID)) + if (!(pte_val(*ptep) & _PAGE_VALID)) goto out; text = (vma->vm_flags & VM_EXEC); @@ -1597,7 +1596,7 @@ * for every cache flush operation. So we do indexed flushes * in that case, which doesn't overly flush the cache too much. */ - if(mm->context != current->mm->context) { + if (mm->context != current->active_mm->context) { /* * Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. @@ -1627,7 +1626,7 @@ * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ - if(mm->context == 0) + if (mm->context == 0) return; #ifdef DEBUG_CACHE @@ -1643,7 +1642,7 @@ * If the page isn't marked valid, the page cannot possibly be * in the cache. */ - if(!(pte_val(*ptep) & _PAGE_VALID)) + if (!(pte_val(*ptep) & _PAGE_VALID)) goto out; text = (vma->vm_flags & VM_EXEC); @@ -1653,7 +1652,7 @@ * for every cache flush operation. So we do indexed flushes * in that case, which doesn't overly flush the cache too much. */ - if(mm->context != current->mm->context) { + if (mm->context != current->active_mm->context) { /* * Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. @@ -1683,7 +1682,7 @@ * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ - if(mm->context == 0) + if (mm->context == 0) return; #ifdef DEBUG_CACHE @@ -1699,7 +1698,7 @@ * If the page isn't marked valid, the page cannot possibly be * in the cache. */ - if(!(pte_val(*ptep) & _PAGE_VALID)) + if (!(pte_val(*ptep) & _PAGE_VALID)) goto out; text = (vma->vm_flags & VM_EXEC); @@ -1709,7 +1708,7 @@ * for every cache flush operation. So we do indexed flushes * in that case, which doesn't overly flush the cache too much. */ - if(mm->context != current->mm->context) { + if (mm->context != current->active_mm->context) { /* * Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. @@ -1754,7 +1753,7 @@ /* If the page isn't marked valid, the page cannot possibly be * in the cache. */ - if(!(pte_val(*ptep) & _PAGE_VALID)) + if (!(pte_val(*ptep) & _PAGE_VALID)) goto out; text = (vma->vm_flags & VM_EXEC); @@ -1764,7 +1763,7 @@ * for every cache flush operation. So we do indexed flushes * in that case, which doesn't overly flush the cache too much. */ - if(mm->context != current->mm->context) { + if (mm->context != current->active_mm->context) { /* Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. */ @@ -1793,7 +1792,7 @@ * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ - if(mm->context == 0) + if (mm->context == 0) return; #ifdef DEBUG_CACHE @@ -1808,7 +1807,7 @@ /* If the page isn't marked valid, the page cannot possibly be * in the cache. */ - if(!(pte_val(*ptep) & _PAGE_VALID)) + if (!(pte_val(*ptep) & _PAGE_VALID)) goto out; text = (vma->vm_flags & VM_EXEC); @@ -1818,7 +1817,7 @@ * for every cache flush operation. So we do indexed flushes * in that case, which doesn't overly flush the cache too much. */ - if(mm == current->mm) { + if (mm == current->active_mm) { blast_dcache16_page(page); if(text) blast_icache16_page(page); @@ -1849,7 +1848,7 @@ * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ - if(mm->context == 0) + if (mm->context == 0) return; #ifdef DEBUG_CACHE @@ -1865,7 +1864,7 @@ * If the page isn't marked valid, the page cannot possibly be * in the cache. */ - if(!(pte_val(*ptep) & _PAGE_PRESENT)) + if (!(pte_val(*ptep) & _PAGE_PRESENT)) goto out; text = (vma->vm_flags & VM_EXEC); @@ -1875,7 +1874,7 @@ * for every cache flush operation. So we do indexed flushes * in that case, which doesn't overly flush the cache too much. */ - if((mm == current->mm) && (pte_val(*ptep) & _PAGE_VALID)) { + if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) { blast_dcache32_page(page); if(text) blast_icache32_page(page); @@ -1907,7 +1906,7 @@ * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ - if(mm->context == 0) + if (mm->context == 0) return; #ifdef DEBUG_CACHE @@ -1933,7 +1932,7 @@ * for every cache flush operation. So we do indexed flushes * in that case, which doesn't overly flush the cache too much. */ - if((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) { + if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) { blast_dcache32_page(page); if(text) blast_icache32_page(page); @@ -1964,7 +1963,7 @@ */ static void r4k_flush_page_to_ram_s16d16i16(struct page * page) { - unsigned long addr = page_address(page) & PAGE_MASK; + unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { #ifdef DEBUG_CACHE @@ -1976,7 +1975,7 @@ static void r4k_flush_page_to_ram_s32d16i16(struct page * page) { - unsigned long addr = page_address(page) & PAGE_MASK; + unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { #ifdef DEBUG_CACHE @@ -1988,7 +1987,7 @@ static void r4k_flush_page_to_ram_s64d16i16(struct page * page) { - unsigned long addr = page_address(page) & PAGE_MASK; + unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { #ifdef DEBUG_CACHE @@ -2000,7 +1999,7 @@ static void r4k_flush_page_to_ram_s128d16i16(struct page * page) { - unsigned long addr = page_address(page) & PAGE_MASK; + unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { #ifdef DEBUG_CACHE @@ -2012,7 +2011,7 @@ static void r4k_flush_page_to_ram_s32d32i32(struct page * page) { - unsigned long addr = page_address(page) & PAGE_MASK; + unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { #ifdef DEBUG_CACHE @@ -2024,7 +2023,7 @@ static void r4k_flush_page_to_ram_s64d32i32(struct page * page) { - unsigned long addr = page_address(page) & PAGE_MASK; + unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { #ifdef DEBUG_CACHE @@ -2036,7 +2035,7 @@ static void r4k_flush_page_to_ram_s128d32i32(struct page * page) { - unsigned long addr = page_address(page) & PAGE_MASK; + unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { #ifdef DEBUG_CACHE @@ -2048,7 +2047,7 @@ static void r4k_flush_page_to_ram_d16i16(struct page * page) { - unsigned long addr = page_address(page) & PAGE_MASK; + unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { unsigned long flags; @@ -2064,7 +2063,7 @@ static void r4k_flush_page_to_ram_d32i32(struct page * page) { - unsigned long addr = page_address(page) & PAGE_MASK; + unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { unsigned long flags; @@ -2263,7 +2262,7 @@ void flush_tlb_mm(struct mm_struct *mm) { - if(mm->context != 0) { + if (mm->context != 0) { unsigned long flags; #ifdef DEBUG_TLB @@ -2271,7 +2270,7 @@ #endif save_and_cli(flags); get_new_mmu_context(mm, asid_cache); - if(mm == current->mm) + if (mm == current->active_mm) set_entryhi(mm->context & 0xff); restore_flags(flags); } @@ -2319,7 +2318,7 @@ set_entryhi(oldpid); } else { get_new_mmu_context(mm, asid_cache); - if(mm == current->mm) + if (mm == current->active_mm) set_entryhi(mm->context & 0xff); } restore_flags(flags); @@ -2328,7 +2327,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long page) { - if(vma->vm_mm->context != 0) { + if (vma->vm_mm->context != 0) { unsigned long flags; int oldpid, newpid, idx; @@ -2399,6 +2398,12 @@ pmd_t *pmdp; pte_t *ptep; int idx, pid; + + /* + * Handle debugger faulting in for debugee. + */ + if (current->active_mm != vma->vm_mm) + return; pid = get_entryhi() & 0xff; diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/mm/umap.c linux/arch/mips/mm/umap.c --- v2.4.0-test5/linux/arch/mips/mm/umap.c Mon Jul 10 16:47:19 2000 +++ linux/arch/mips/mm/umap.c Mon Aug 7 21:02:27 2000 @@ -115,10 +115,10 @@ static inline void free_pte(pte_t page) { if (pte_present(page)) { - unsigned long nr = pte_pagenr(page); - if (nr >= max_mapnr || PageReserved(mem_map+nr)) + struct page *ptpage = pte_page(page); + if ((!VALID_PAGE(ptpage)) || PageReserved(ptpage)) return; - __free_page(pte_page(page)); + __free_page(ptpage); if (current->mm->rss <= 0) return; current->mm->rss--; diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/orion/irq.c linux/arch/mips/orion/irq.c --- v2.4.0-test5/linux/arch/mips/orion/irq.c Fri Jul 14 12:12:05 2000 +++ linux/arch/mips/orion/irq.c Fri Aug 4 16:15:38 2000 @@ -25,9 +25,6 @@ void (*board_time_init)(struct irqaction *irq); extern asmlinkage void orionIRQ(void); -irq_cpustat_t irq_stat [NR_CPUS]; -unsigned int local_bh_count[NR_CPUS]; -unsigned int local_irq_count[NR_CPUS]; unsigned long spurious_count = 0; irq_desc_t irq_desc[NR_IRQS]; @@ -186,7 +183,7 @@ irq_exit(cpu); - if (softirq_state[cpu].active&softirq_state[cpu].mask) + if (softirq_active(cpu)&softirq_mask(cpu)) do_softirq(); /* unmasking and bottom half handling is done magically for us. */ diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/sgi/kernel/indy_int.c linux/arch/mips/sgi/kernel/indy_int.c --- v2.4.0-test5/linux/arch/mips/sgi/kernel/indy_int.c Tue May 23 15:31:33 2000 +++ linux/arch/mips/sgi/kernel/indy_int.c Fri Aug 4 16:15:37 2000 @@ -55,8 +55,6 @@ * interrupt controllers, without having to do assembly magic. */ -irq_cpustat_t irq_stat [NR_CPUS]; - /* #define DEBUG_SGINT */ struct sgi_int2_regs *sgi_i2regs; @@ -72,8 +70,6 @@ extern asmlinkage void indyIRQ(void); -unsigned int local_bh_count[NR_CPUS]; -unsigned int local_irq_count[NR_CPUS]; unsigned long spurious_count = 0; /* Local IRQ's are layed out logically like this: diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/sgi/kernel/setup.c linux/arch/mips/sgi/kernel/setup.c --- v2.4.0-test5/linux/arch/mips/sgi/kernel/setup.c Mon Jul 10 16:47:19 2000 +++ linux/arch/mips/sgi/kernel/setup.c Wed Aug 9 13:46:02 2000 @@ -130,9 +130,9 @@ int __init page_is_ram(unsigned long pagenr) { - if (pagenr < MAP_NR(PAGE_OFFSET + 0x2000UL)) + if ((pagenr< MAP_NR(PAGE_OFFSET + 0x08002000)) + if ((pagenr< 0x08002000) return 1; return 0; } @@ -180,7 +180,7 @@ */ struct sgi_ioc_timers *p; volatile unsigned char *tcwp, *tc2p; - unsigned long r4k_ticks[3]; + unsigned long r4k_ticks[3] = { 0, 0, 0 }; unsigned long r4k_next; /* Figure out the r4k offset, the algorithm is very simple @@ -198,15 +198,16 @@ tc2p = &p->tcnt2; printk("Calibrating system timer... "); - dosample(tcwp, tc2p); /* First sample. */ - dosample(tcwp, tc2p); /* Eat one. */ - r4k_ticks[0] = dosample(tcwp, tc2p); /* Second sample. */ - dosample(tcwp, tc2p); /* Eat another. */ - r4k_ticks[1] += dosample (tcwp, tc2p); /* Third sample. */ + dosample(tcwp, tc2p); /* Prime cache. */ + dosample(tcwp, tc2p); /* Prime cache. */ + /* Zero is NOT an option. */ + while (!r4k_ticks[0]) + r4k_ticks[0] = dosample (tcwp, tc2p); + while (!r4k_ticks[1]) + r4k_ticks[1] = dosample (tcwp, tc2p); if (r4k_ticks[0] != r4k_ticks[1]) { printk ("warning: timer counts differ, retrying..."); - dosample (tcwp, tc2p); r4k_ticks[2] = dosample (tcwp, tc2p); if (r4k_ticks[2] == r4k_ticks[0] || r4k_ticks[2] == r4k_ticks[1]) diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips/tools/offset.c linux/arch/mips/tools/offset.c --- v2.4.0-test5/linux/arch/mips/tools/offset.c Fri Jul 14 12:12:05 2000 +++ linux/arch/mips/tools/offset.c Thu Jul 27 18:36:54 2000 @@ -80,6 +80,7 @@ offset("#define TASK_FLAGS ", struct task_struct, flags); offset("#define TASK_SIGPENDING ", struct task_struct, sigpending); offset("#define TASK_NEED_RESCHED ", struct task_struct, need_resched); + offset("#define TASK_PTRACE ", struct task_struct, ptrace); offset("#define TASK_COUNTER ", struct task_struct, counter); offset("#define TASK_NICE ", struct task_struct, nice); offset("#define TASK_MM ", struct task_struct, mm); diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/Makefile linux/arch/mips64/Makefile --- v2.4.0-test5/linux/arch/mips64/Makefile Mon Jul 10 16:47:20 2000 +++ linux/arch/mips64/Makefile Thu Jul 27 18:36:54 2000 @@ -1,4 +1,3 @@ -# $Id: Makefile,v 1.5 2000/01/21 22:34:03 ralf Exp $ # # This file is subject to the terms and conditions of the GNU General Public # License. See the file "COPYING" in the main directory of this archive @@ -33,7 +32,7 @@ # machines may also. Since BFD is incredibly buggy with respect to # crossformat linking we rely on the elf2ecoff tool for format conversion. # -CFLAGS += -mabi=64 -G 0 -mno-abicalls -fno-pic -pipe +CFLAGS += -mabi=64 -G 0 -mno-abicalls -fno-pic -Wa,--trap -pipe LINKFLAGS += -G 0 -static # -N MODFLAGS += -mlong-calls diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/arc/memory.c linux/arch/mips64/arc/memory.c --- v2.4.0-test5/linux/arch/mips64/arc/memory.c Mon Jul 10 16:47:20 2000 +++ linux/arch/mips64/arc/memory.c Mon Aug 7 21:02:27 2000 @@ -233,8 +233,8 @@ addr = PAGE_OFFSET + (unsigned long) (long) p->base; end = addr + (unsigned long) (long) p->size; while (addr < end) { - ClearPageReserved(mem_map + MAP_NR(addr)); - set_page_count(mem_map + MAP_NR(addr), 1); + ClearPageReserved(virt_to_page(addr)); + set_page_count(virt_to_page(addr), 1); free_page(addr); addr += PAGE_SIZE; freed += PAGE_SIZE; diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/config.in linux/arch/mips64/config.in --- v2.4.0-test5/linux/arch/mips64/config.in Fri Jul 14 12:12:05 2000 +++ linux/arch/mips64/config.in Thu Jul 27 18:36:54 2000 @@ -11,15 +11,6 @@ endmenu mainmenu_option next_comment -comment 'Loadable module support' -bool 'Enable loadable module support' CONFIG_MODULES -if [ "$CONFIG_MODULES" = "y" ]; then - bool ' Set version information on all module symbols' CONFIG_MODVERSIONS - bool ' Kernel module loader' CONFIG_KMOD -fi -endmenu - -mainmenu_option next_comment comment 'Machine selection' bool 'Support for SGI IP22' CONFIG_SGI_IP22 bool 'Support for SGI IP27' CONFIG_SGI_IP27 @@ -117,6 +108,14 @@ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC endmenu + +mainmenu_option next_comment +comment 'Loadable module support' +bool 'Enable loadable module support' CONFIG_MODULES +if [ "$CONFIG_MODULES" = "y" ]; then + bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS + bool 'Kernel module loader' CONFIG_KMOD +fi source drivers/pci/Config.in diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/defconfig linux/arch/mips64/defconfig --- v2.4.0-test5/linux/arch/mips64/defconfig Fri Jul 14 12:12:05 2000 +++ linux/arch/mips64/defconfig Thu Jul 27 18:36:54 2000 @@ -327,7 +327,7 @@ # # CONFIG_FTAPE is not set # CONFIG_DRM is not set -# CONFIG_DRM_TDFX is not set +# CONFIG_AGP is not set # # File systems diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/defconfig-ip22 linux/arch/mips64/defconfig-ip22 --- v2.4.0-test5/linux/arch/mips64/defconfig-ip22 Fri Jul 14 12:12:05 2000 +++ linux/arch/mips64/defconfig-ip22 Thu Jul 27 18:36:54 2000 @@ -246,7 +246,7 @@ # # CONFIG_FTAPE is not set # CONFIG_DRM is not set -# CONFIG_DRM_TDFX is not set +# CONFIG_AGP is not set # # File systems diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/defconfig-ip27 linux/arch/mips64/defconfig-ip27 --- v2.4.0-test5/linux/arch/mips64/defconfig-ip27 Fri Jul 14 12:12:05 2000 +++ linux/arch/mips64/defconfig-ip27 Thu Jul 27 18:36:54 2000 @@ -327,7 +327,7 @@ # # CONFIG_FTAPE is not set # CONFIG_DRM is not set -# CONFIG_DRM_TDFX is not set +# CONFIG_AGP is not set # # File systems diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/kernel/binfmt_elf32.c linux/arch/mips64/kernel/binfmt_elf32.c --- v2.4.0-test5/linux/arch/mips64/kernel/binfmt_elf32.c Fri Jul 14 12:12:05 2000 +++ linux/arch/mips64/kernel/binfmt_elf32.c Thu Jul 27 18:36:54 2000 @@ -1,5 +1,4 @@ -/* $Id: binfmt_elf32.c,v 1.1 1999/11/24 06:56:13 ralf Exp $ - * +/* * Support for 32-bit Linux/MIPS ELF binaries. * * Copyright (C) 1999 Ralf Baechle @@ -28,7 +27,8 @@ typedef double elf_fpreg_t; typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; -#define elf_check_arch(x) ((x)->e_machine == EM_MIPS || (x)->e_machine == EM_MIPS_RS4_BE) +#define elf_check_arch(x) \ + ((x)->e_machine == EM_MIPS || (x)->e_machine == EM_MIPS_RS4_BE) #define TASK32_SIZE 0x80000000UL #undef ELF_ET_DYN_BASE diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/kernel/entry.S linux/arch/mips64/kernel/entry.S --- v2.4.0-test5/linux/arch/mips64/kernel/entry.S Tue May 23 15:31:33 2000 +++ linux/arch/mips64/kernel/entry.S Fri Aug 4 16:15:37 2000 @@ -35,14 +35,14 @@ FEXPORT(ret_from_sys_call) FEXPORT(ret_from_irq) - la t1, softirq_state + la t1, irq_stat # softirq_active #ifdef CONFIG_SMP lwu t0, TASK_PROCESSOR($28) dsll t0, t0, 5 daddu t1, t0 #endif - lw t0, 0 (t1) - lw t1, 4 (t1) # unused delay slot + lw t0, 0 (t1) # softirq_active + lw t1, 4 (t1) # softirq_mask. unused delay slot and t0, t1 bnez t0, handle_softirq 9: ld t0, PT_STATUS(sp) # returning to kernel mode? diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/kernel/linux32.c linux/arch/mips64/kernel/linux32.c --- v2.4.0-test5/linux/arch/mips64/kernel/linux32.c Mon Jul 10 16:47:20 2000 +++ linux/arch/mips64/kernel/linux32.c Thu Jul 27 18:36:54 2000 @@ -19,9 +19,13 @@ #include #include #include +#include +#include +#include #include #include +#include #define A(__x) ((unsigned long)(__x)) @@ -359,16 +363,18 @@ nargs(unsigned int arg, char **ap) { char *ptr; - int n; + int n, ret; n = 0; do { /* egcs is stupid */ if (!access_ok(VERIFY_READ, arg, sizeof (unsigned int))) return -EFAULT; - __get_user((long)ptr,(int *)A(arg)); - if (ap) - *ap++ = ptr; + if (IS_ERR(ret = __get_user((long)ptr,(int *)A(arg)))) + return ret; + if (ap) /* no access_ok needed, we allocated */ + if (IS_ERR(ret = __put_user(ptr, ap++))) + return ret; arg += sizeof(unsigned int); n++; } while (ptr); @@ -387,7 +393,11 @@ char * filename; na = nargs(argv, NULL); + if (IS_ERR(na)) + return(na); ne = nargs(envp, NULL); + if (IS_ERR(ne)) + return(ne); len = (na + ne + 2) * sizeof(*av); /* * kmalloc won't work because the `sys_exec' code will attempt @@ -403,20 +413,25 @@ up(¤t->mm->mmap_sem); if (IS_ERR(av)) - return((long) av); + return (long) av; ae = av + na + 1; - av[na] = (char *)0; - ae[ne] = (char *)0; - (void)nargs(argv, av); - (void)nargs(envp, ae); + if (IS_ERR(r = __put_user(0, (av + na)))) + goto out; + if (IS_ERR(r = __put_user(0, (ae + ne)))) + goto out; + if (IS_ERR(r = nargs(argv, av))) + goto out; + if (IS_ERR(r = nargs(envp, ae))) + goto out; filename = getname((char *) (long)regs.regs[4]); r = PTR_ERR(filename); if (IS_ERR(filename)) - return(r); + goto out; r = do_execve(filename, av, ae, ®s); putname(filename); if (IS_ERR(r)) +out: sys_munmap((unsigned long)av, len); return(r); } @@ -1337,3 +1352,413 @@ return sys_fcntl(fd, cmd, (unsigned long)arg); } } + +struct msgbuf32 { s32 mtype; char mtext[1]; }; + +struct ipc_perm32 +{ + key_t key; + __kernel_uid_t32 uid; + __kernel_gid_t32 gid; + __kernel_uid_t32 cuid; + __kernel_gid_t32 cgid; + __kernel_mode_t32 mode; + unsigned short seq; +}; + +struct semid_ds32 { + struct ipc_perm32 sem_perm; /* permissions .. see ipc.h */ + __kernel_time_t32 sem_otime; /* last semop time */ + __kernel_time_t32 sem_ctime; /* last change time */ + u32 sem_base; /* ptr to first semaphore in array */ + u32 sem_pending; /* pending operations to be processed */ + u32 sem_pending_last; /* last pending operation */ + u32 undo; /* undo requests on this array */ + unsigned short sem_nsems; /* no. of semaphores in array */ +}; + +struct msqid_ds32 +{ + struct ipc_perm32 msg_perm; + u32 msg_first; + u32 msg_last; + __kernel_time_t32 msg_stime; + __kernel_time_t32 msg_rtime; + __kernel_time_t32 msg_ctime; + u32 wwait; + u32 rwait; + unsigned short msg_cbytes; + unsigned short msg_qnum; + unsigned short msg_qbytes; + __kernel_ipc_pid_t32 msg_lspid; + __kernel_ipc_pid_t32 msg_lrpid; +}; + +struct shmid_ds32 { + struct ipc_perm32 shm_perm; + int shm_segsz; + __kernel_time_t32 shm_atime; + __kernel_time_t32 shm_dtime; + __kernel_time_t32 shm_ctime; + __kernel_ipc_pid_t32 shm_cpid; + __kernel_ipc_pid_t32 shm_lpid; + unsigned short shm_nattch; +}; + +#define IPCOP_MASK(__x) (1UL << (__x)) + +static int +do_sys32_semctl(int first, int second, int third, void *uptr) +{ + union semun fourth; + u32 pad; + int err, err2; + struct semid64_ds s; + struct semid_ds32 *usp; + mm_segment_t old_fs; + + if (!uptr) + return -EINVAL; + err = -EFAULT; + if (get_user (pad, (u32 *)uptr)) + return err; + if(third == SETVAL) + fourth.val = (int)pad; + else + fourth.__pad = (void *)A(pad); + switch (third) { + + case IPC_INFO: + case IPC_RMID: + case IPC_SET: + case SEM_INFO: + case GETVAL: + case GETPID: + case GETNCNT: + case GETZCNT: + case GETALL: + case SETVAL: + case SETALL: + err = sys_semctl (first, second, third, fourth); + break; + + case IPC_STAT: + case SEM_STAT: + usp = (struct semid_ds32 *)A(pad); + fourth.__pad = &s; + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_semctl (first, second, third, fourth); + set_fs (old_fs); + err2 = put_user(s.sem_perm.key, &usp->sem_perm.key); + err2 |= __put_user(s.sem_perm.uid, &usp->sem_perm.uid); + err2 |= __put_user(s.sem_perm.gid, &usp->sem_perm.gid); + err2 |= __put_user(s.sem_perm.cuid, + &usp->sem_perm.cuid); + err2 |= __put_user (s.sem_perm.cgid, + &usp->sem_perm.cgid); + err2 |= __put_user (s.sem_perm.mode, + &usp->sem_perm.mode); + err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq); + err2 |= __put_user (s.sem_otime, &usp->sem_otime); + err2 |= __put_user (s.sem_ctime, &usp->sem_ctime); + err2 |= __put_user (s.sem_nsems, &usp->sem_nsems); + if (err2) + err = -EFAULT; + break; + + } + + return err; +} + +static int +do_sys32_msgsnd (int first, int second, int third, void *uptr) +{ + struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf) + + 4, GFP_USER); + struct msgbuf32 *up = (struct msgbuf32 *)uptr; + mm_segment_t old_fs; + int err; + + if (!p) + return -ENOMEM; + err = get_user (p->mtype, &up->mtype); + err |= __copy_from_user (p->mtext, &up->mtext, second); + if (err) + goto out; + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_msgsnd (first, p, second, third); + set_fs (old_fs); +out: + kfree (p); + return err; +} + +static int +do_sys32_msgrcv (int first, int second, int msgtyp, int third, + int version, void *uptr) +{ + struct msgbuf32 *up; + struct msgbuf *p; + mm_segment_t old_fs; + int err; + + if (!version) { + struct ipc_kludge *uipck = (struct ipc_kludge *)uptr; + struct ipc_kludge ipck; + + err = -EINVAL; + if (!uptr) + goto out; + err = -EFAULT; + if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge))) + goto out; + uptr = (void *)A(ipck.msgp); + msgtyp = ipck.msgtyp; + } + err = -ENOMEM; + p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER); + if (!p) + goto out; + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_msgrcv (first, p, second + 4, msgtyp, third); + set_fs (old_fs); + if (err < 0) + goto free_then_out; + up = (struct msgbuf32 *)uptr; + if (put_user (p->mtype, &up->mtype) || + __copy_to_user (&up->mtext, p->mtext, err)) + err = -EFAULT; +free_then_out: + kfree (p); +out: + return err; +} + +static int +do_sys32_msgctl (int first, int second, void *uptr) +{ + int err = -EINVAL, err2; + struct msqid_ds m; + struct msqid64_ds m64; + struct msqid_ds32 *up = (struct msqid_ds32 *)uptr; + mm_segment_t old_fs; + + switch (second) { + + case IPC_INFO: + case IPC_RMID: + case MSG_INFO: + err = sys_msgctl (first, second, (struct msqid_ds *)uptr); + break; + + case IPC_SET: + err = get_user (m.msg_perm.uid, &up->msg_perm.uid); + err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid); + err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode); + err |= __get_user (m.msg_qbytes, &up->msg_qbytes); + if (err) + break; + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_msgctl (first, second, &m); + set_fs (old_fs); + break; + + case IPC_STAT: + case MSG_STAT: + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_msgctl (first, second, (void *) &m64); + set_fs (old_fs); + err2 = put_user (m64.msg_perm.key, &up->msg_perm.key); + err2 |= __put_user(m64.msg_perm.uid, &up->msg_perm.uid); + err2 |= __put_user(m64.msg_perm.gid, &up->msg_perm.gid); + err2 |= __put_user(m64.msg_perm.cuid, &up->msg_perm.cuid); + err2 |= __put_user(m64.msg_perm.cgid, &up->msg_perm.cgid); + err2 |= __put_user(m64.msg_perm.mode, &up->msg_perm.mode); + err2 |= __put_user(m64.msg_perm.seq, &up->msg_perm.seq); + err2 |= __put_user(m64.msg_stime, &up->msg_stime); + err2 |= __put_user(m64.msg_rtime, &up->msg_rtime); + err2 |= __put_user(m64.msg_ctime, &up->msg_ctime); + err2 |= __put_user(m64.msg_cbytes, &up->msg_cbytes); + err2 |= __put_user(m64.msg_qnum, &up->msg_qnum); + err2 |= __put_user(m64.msg_qbytes, &up->msg_qbytes); + err2 |= __put_user(m64.msg_lspid, &up->msg_lspid); + err2 |= __put_user(m64.msg_lrpid, &up->msg_lrpid); + if (err2) + err = -EFAULT; + break; + + } + + return err; +} + +static int +do_sys32_shmat (int first, int second, int third, int version, void *uptr) +{ + unsigned long raddr; + u32 *uaddr = (u32 *)A((u32)third); + int err = -EINVAL; + + if (version == 1) + return err; + if (version == 1) + return err; + err = sys_shmat (first, uptr, second, &raddr); + if (err) + return err; + err = put_user (raddr, uaddr); + return err; +} + +static int +do_sys32_shmctl (int first, int second, void *uptr) +{ + int err = -EFAULT, err2; + struct shmid_ds s; + struct shmid64_ds s64; + struct shmid_ds32 *up = (struct shmid_ds32 *)uptr; + mm_segment_t old_fs; + struct shm_info32 { + int used_ids; + u32 shm_tot, shm_rss, shm_swp; + u32 swap_attempts, swap_successes; + } *uip = (struct shm_info32 *)uptr; + struct shm_info si; + + switch (second) { + + case IPC_INFO: + case IPC_RMID: + case SHM_LOCK: + case SHM_UNLOCK: + err = sys_shmctl (first, second, (struct shmid_ds *)uptr); + break; + case IPC_SET: + err = get_user (s.shm_perm.uid, &up->shm_perm.uid); + err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid); + err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode); + if (err) + break; + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_shmctl (first, second, &s); + set_fs (old_fs); + break; + + case IPC_STAT: + case SHM_STAT: + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_shmctl (first, second, (void *) &s64); + set_fs (old_fs); + if (err < 0) + break; + err2 = put_user (s64.shm_perm.key, &up->shm_perm.key); + err2 |= __put_user (s64.shm_perm.uid, &up->shm_perm.uid); + err2 |= __put_user (s64.shm_perm.gid, &up->shm_perm.gid); + err2 |= __put_user (s64.shm_perm.cuid, + &up->shm_perm.cuid); + err2 |= __put_user (s64.shm_perm.cgid, + &up->shm_perm.cgid); + err2 |= __put_user (s64.shm_perm.mode, + &up->shm_perm.mode); + err2 |= __put_user (s64.shm_perm.seq, &up->shm_perm.seq); + err2 |= __put_user (s64.shm_atime, &up->shm_atime); + err2 |= __put_user (s64.shm_dtime, &up->shm_dtime); + err2 |= __put_user (s64.shm_ctime, &up->shm_ctime); + err2 |= __put_user (s64.shm_segsz, &up->shm_segsz); + err2 |= __put_user (s64.shm_nattch, &up->shm_nattch); + err2 |= __put_user (s64.shm_cpid, &up->shm_cpid); + err2 |= __put_user (s64.shm_lpid, &up->shm_lpid); + if (err2) + err = -EFAULT; + break; + + case SHM_INFO: + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_shmctl (first, second, (void *)&si); + set_fs (old_fs); + if (err < 0) + break; + err2 = put_user (si.used_ids, &uip->used_ids); + err2 |= __put_user (si.shm_tot, &uip->shm_tot); + err2 |= __put_user (si.shm_rss, &uip->shm_rss); + err2 |= __put_user (si.shm_swp, &uip->shm_swp); + err2 |= __put_user (si.swap_attempts, + &uip->swap_attempts); + err2 |= __put_user (si.swap_successes, + &uip->swap_successes); + if (err2) + err = -EFAULT; + break; + + } + return err; +} + +asmlinkage long +sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) +{ + int version, err; + + version = call >> 16; /* hack for backward compatibility */ + call &= 0xffff; + + switch (call) { + + case SEMOP: + /* struct sembuf is the same on 32 and 64bit :)) */ + err = sys_semop (first, (struct sembuf *)A(ptr), + second); + break; + case SEMGET: + err = sys_semget (first, second, third); + break; + case SEMCTL: + err = do_sys32_semctl (first, second, third, + (void *)A(ptr)); + break; + + case MSGSND: + err = do_sys32_msgsnd (first, second, third, + (void *)A(ptr)); + break; + case MSGRCV: + err = do_sys32_msgrcv (first, second, fifth, third, + version, (void *)A(ptr)); + break; + case MSGGET: + err = sys_msgget ((key_t) first, second); + break; + case MSGCTL: + err = do_sys32_msgctl (first, second, (void *)A(ptr)); + break; + + case SHMAT: + err = do_sys32_shmat (first, second, third, + version, (void *)A(ptr)); + break; + case SHMDT: + err = sys_shmdt ((char *)A(ptr)); + break; + case SHMGET: + err = sys_shmget (first, second, third); + break; + case SHMCTL: + err = do_sys32_shmctl (first, second, (void *)A(ptr)); + break; + default: + err = -EINVAL; + break; + } + + return err; +} + diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/kernel/mips64_ksyms.c linux/arch/mips64/kernel/mips64_ksyms.c --- v2.4.0-test5/linux/arch/mips64/kernel/mips64_ksyms.c Fri Jul 14 12:12:05 2000 +++ linux/arch/mips64/kernel/mips64_ksyms.c Thu Jul 27 18:36:54 2000 @@ -81,7 +81,7 @@ * Functions to control caches. */ EXPORT_SYMBOL(_flush_page_to_ram); -EXPORT_SYMBOL(_flush_cache_all); +EXPORT_SYMBOL(_flush_cache_l1); #ifndef CONFIG_COHERENT_IO EXPORT_SYMBOL(_dma_cache_wback_inv); EXPORT_SYMBOL(_dma_cache_inv); diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/kernel/scall_64.S linux/arch/mips64/kernel/scall_64.S --- v2.4.0-test5/linux/arch/mips64/kernel/scall_64.S Tue May 23 15:31:33 2000 +++ linux/arch/mips64/kernel/scall_64.S Fri Aug 4 16:15:37 2000 @@ -1,11 +1,10 @@ -/* $Id: scall_64.S,v 1.7 2000/02/23 00:41:00 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995, 1996, 1997, 1998, 1999 by Ralf Baechle - * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000 by Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ #include #include @@ -17,7 +16,7 @@ #include /* This duplicates the definition from */ -#define PF_TRACESYS 0x00000020 /* tracing system calls */ +#define PT_TRACESYS 0x00000002 /* tracing system calls */ /* This duplicates the definition from */ #define SIGILL 4 /* Illegal instruction (ANSI). */ @@ -48,8 +47,8 @@ sd a3, PT_R26(sp) # save a3 for syscall restarting - ld t0, TASK_FLAGS($28) # syscall tracing enabled? - andi t0, PF_TRACESYS + ld t0, TASK_PTRACE($28) # syscall tracing enabled? + andi t0, PT_TRACESYS bnez t0, trace_a_syscall jalr t2 # Do The Real Thing (TM) @@ -64,8 +63,8 @@ 1: sd v0, PT_R2(sp) # result FEXPORT(ret_from_sys_call_64) - lw t0, softirq_state - lw t1, softirq_state+4 # unused delay slot + lw t0, irq_stat # softirq_active + lw t1, irq_stat+4 # softirq_mask. unused delay slot and t0, t1 bnez t0, handle_softirq_64 diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/kernel/scall_o32.S linux/arch/mips64/kernel/scall_o32.S --- v2.4.0-test5/linux/arch/mips64/kernel/scall_o32.S Mon Jul 10 16:47:20 2000 +++ linux/arch/mips64/kernel/scall_o32.S Fri Aug 4 16:15:37 2000 @@ -20,7 +20,7 @@ #include /* This duplicates the definition from */ -#define PF_TRACESYS 0x00000020 /* tracing system calls */ +#define PT_TRACESYS 0x00000002 /* tracing system calls */ /* This duplicates the definition from */ #define SIGILL 4 /* Illegal instruction (ANSI). */ @@ -60,8 +60,8 @@ bgez t0, stackargs stack_done: - ld t0, TASK_FLAGS($28) # syscall tracing enabled? - andi t0, PF_TRACESYS + ld t0, TASK_PTRACE($28) # syscall tracing enabled? + andi t0, PT_TRACESYS bnez t0, trace_a_syscall jalr t2 # Do The Real Thing (TM) @@ -76,8 +76,8 @@ 1: sd v0, PT_R2(sp) # result FEXPORT(o32_ret_from_sys_call) - lw t0, softirq_state - lw t1, softirq_state+4 # unused delay slot + lw t0, irq_stat # softirq_active + lw t1, irq_stat+4 # softirq_mask. unused delay slot and t0, t1 bnez t0, o32_handle_softirq @@ -318,7 +318,7 @@ sys sys32_wait4 4 sys sys_swapoff 1 /* 4115 */ sys sys_sysinfo 1 - sys sys_ipc 6 + sys sys32_ipc 6 sys sys_fsync 1 sys sys32_sigreturn 0 sys sys_clone 0 /* 4120 */ diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/kernel/smp.c linux/arch/mips64/kernel/smp.c --- v2.4.0-test5/linux/arch/mips64/kernel/smp.c Mon Jul 10 16:47:20 2000 +++ linux/arch/mips64/kernel/smp.c Thu Jul 27 18:36:54 2000 @@ -71,7 +71,6 @@ extern void allowboot(void); init_new_context(current, &init_mm); - global_irq_holder = 0; current->processor = 0; init_idle(); smp_tune_scheduling(); diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/kernel/syscall.c linux/arch/mips64/kernel/syscall.c --- v2.4.0-test5/linux/arch/mips64/kernel/syscall.c Mon Jul 10 16:47:20 2000 +++ linux/arch/mips64/kernel/syscall.c Thu Jul 27 18:36:54 2000 @@ -217,7 +217,7 @@ return 0; case FLUSH_CACHE: - flush_cache_all(); + flush_cache_l1(); return 0; case MIPS_RDNVRAM: diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/mm/andes.c linux/arch/mips64/mm/andes.c --- v2.4.0-test5/linux/arch/mips64/mm/andes.c Mon Jul 10 16:47:20 2000 +++ linux/arch/mips64/mm/andes.c Thu Jul 27 18:36:54 2000 @@ -1,11 +1,11 @@ -/* $Id: andes.c,v 1.7 2000/03/13 22:43:25 kanoj Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 1997, 1998, 1999 Ralf Baechle (ralf@gnu.org) * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 2000 Kanoj Sarcar (kanoj@sgi.com) */ #include #include @@ -18,19 +18,25 @@ #include #include +static int scache_lsz64; + /* CP0 hazard avoidance. I think we can drop this for the R10000. */ #define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ "nop; nop; nop; nop; nop; nop;\n\t" \ ".set reorder\n\t") -/* R10000 has no Create_Dirty type cacheops. */ +/* + * This version has been tuned on an Origin. For other machines the arguments + * of the pref instructin may have to be tuned differently. + */ static void andes_clear_page(void * page) { __asm__ __volatile__( ".set\tnoreorder\n\t" ".set\tnoat\n\t" "daddiu\t$1,%0,%2\n" - "1:\tsd\t$0,(%0)\n\t" + "1:\tpref 7,512(%0)\n\t" + "sd\t$0,(%0)\n\t" "sd\t$0,8(%0)\n\t" "sd\t$0,16(%0)\n\t" "sd\t$0,24(%0)\n\t" @@ -47,147 +53,78 @@ :"$1", "memory"); } +/* R10000 has no Create_Dirty type cacheops. */ static void andes_copy_page(void * to, void * from) { - unsigned long dummy1, dummy2, reg1, reg2; + unsigned long dummy1, dummy2, reg1, reg2, reg3, reg4; __asm__ __volatile__( ".set\tnoreorder\n\t" ".set\tnoat\n\t" - "daddiu\t$1,%0,%6\n" - "1:\tld\t%2,(%1)\n\t" + "daddiu\t$1,%0,%8\n" + "1:\tpref\t0,2*128(%1)\n\t" + "pref\t1,2*128(%0)\n\t" + "ld\t%2,(%1)\n\t" "ld\t%3,8(%1)\n\t" + "ld\t%4,16(%1)\n\t" + "ld\t%5,24(%1)\n\t" "sd\t%2,(%0)\n\t" "sd\t%3,8(%0)\n\t" - "ld\t%2,16(%1)\n\t" - "ld\t%3,24(%1)\n\t" - "sd\t%2,16(%0)\n\t" - "sd\t%3,24(%0)\n\t" + "sd\t%4,16(%0)\n\t" + "sd\t%5,24(%0)\n\t" "daddiu\t%0,64\n\t" "daddiu\t%1,64\n\t" "ld\t%2,-32(%1)\n\t" "ld\t%3,-24(%1)\n\t" + "ld\t%4,-16(%1)\n\t" + "ld\t%5,-8(%1)\n\t" "sd\t%2,-32(%0)\n\t" "sd\t%3,-24(%0)\n\t" - "ld\t%2,-16(%1)\n\t" - "ld\t%3,-8(%1)\n\t" - "sd\t%2,-16(%0)\n\t" + "sd\t%4,-16(%0)\n\t" "bne\t$1,%0,1b\n\t" - " sd\t%3,-8(%0)\n\t" + " sd\t%5,-8(%0)\n\t" ".set\tat\n\t" ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2) + :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2), + "=&r" (reg3), "=&r" (reg4) :"0" (to), "1" (from), "I" (PAGE_SIZE)); } /* Cache operations. These are only used with the virtual memory system, not for non-coherent I/O so it's ok to ignore the secondary caches. */ static void -andes_flush_cache_all(void) +andes_flush_cache_l1(void) { blast_dcache32(); blast_icache64(); } +/* + * This is only used during initialization time. vmalloc() also calls + * this, but that will be changed pretty soon. + */ static void -andes_flush_cache_mm(struct mm_struct *mm) +andes_flush_cache_l2(void) { - if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { -#ifdef DEBUG_CACHE - printk("cmm[%d]", (int)mm->context); -#endif - andes_flush_cache_all(); + switch (sc_lsize()) { + case 64: + blast_scache64(); + break; + case 128: + blast_scache128(); + break; + default: + printk("Unknown L2 line size\n"); + while(1); } } -static void -andes_flush_cache_range(struct mm_struct *mm, unsigned long start, - unsigned long end) +void +andes_flush_icache_page(unsigned long page) { - if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { - unsigned long flags; - -#ifdef DEBUG_CACHE - printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); -#endif - save_and_cli(flags); - blast_dcache32(); blast_icache64(); - restore_flags(flags); - } -} - -static void -andes_flush_cache_page(struct vm_area_struct *vma, unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - int text; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (CPU_CONTEXT(smp_processor_id(), mm) == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - save_and_cli(flags); - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* - * If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if(!(pte_val(*ptep) & _PAGE_PRESENT)) - goto out; - - text = (vma->vm_flags & VM_EXEC); - /* - * Doing flushes for another ASID than the current one is - * too difficult since stupid R4k caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if ((mm == current->mm) && (pte_val(*ptep) & _PAGE_VALID)) { - blast_dcache32_page(page); - if(text) - blast_icache64_page(page); - } else { - /* - * Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = (CKSEG0 + (page & (dcache_size - 1))); - blast_dcache32_page_indexed(page); - if(text) - blast_icache64_page_indexed(page); - } -out: - restore_flags(flags); -} - -/* Hoo hum... will this ever be called for an address that is not in CKSEG0 - and not cacheable? */ -static void -andes_flush_page_to_ram(struct page * page) -{ - unsigned long addr = page_address(page) & PAGE_MASK; - - if ((addr >= K0BASE_NONCOH && addr < (0xb0UL << 56)) - || (addr >= KSEG0 && addr < KSEG1) - || (addr >= KSEG2)) { -#ifdef DEBUG_CACHE - printk("cram[%08lx]", addr); -#endif - blast_dcache32_page(addr); - } + if (scache_lsz64) + blast_scache64_page(page); + else + blast_scache128_page(page); } static void @@ -355,6 +292,12 @@ pte_t *ptep; int idx, pid; + /* + * Handle debugger faulting in for debugee. + */ + if (current->active_mm != vma->vm_mm) + return; + __save_and_cli(flags); pid = get_entryhi() & 0xff; @@ -440,24 +383,33 @@ _clear_page = andes_clear_page; _copy_page = andes_copy_page; - _flush_cache_all = andes_flush_cache_all; - _flush_cache_mm = andes_flush_cache_mm; - _flush_cache_range = andes_flush_cache_range; - _flush_cache_page = andes_flush_cache_page; + _flush_cache_l1 = andes_flush_cache_l1; + _flush_cache_l2 = andes_flush_cache_l2; _flush_cache_sigtramp = andes_flush_cache_sigtramp; - _flush_page_to_ram = andes_flush_page_to_ram; _flush_tlb_all = andes_flush_tlb_all; _flush_tlb_mm = andes_flush_tlb_mm; _flush_tlb_range = andes_flush_tlb_range; _flush_tlb_page = andes_flush_tlb_page; + + switch (sc_lsize()) { + case 64: + scache_lsz64 = 1; + break; + case 128: + scache_lsz64 = 0; + break; + default: + printk("Unknown L2 line size\n"); + while(1); + } update_mmu_cache = andes_update_mmu_cache; _show_regs = andes_show_regs; _user_mode = andes_user_mode; - flush_cache_all(); + flush_cache_l1(); /* * You should never change this register: diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/mm/init.c linux/arch/mips64/mm/init.c --- v2.4.0-test5/linux/arch/mips64/mm/init.c Mon Jul 10 16:47:20 2000 +++ linux/arch/mips64/mm/init.c Mon Aug 7 21:02:27 2000 @@ -200,7 +200,7 @@ asmlinkage int sys_cacheflush(void *addr, int bytes, int cache) { /* XXX Just get it working for now... */ - flush_cache_all(); + flush_cache_l1(); return 0; } @@ -215,7 +215,8 @@ unsigned long setup_zero_pages(void) { - unsigned long order, size, pg; + unsigned long order, size; + struct page *page; switch (mips_cputype) { case CPU_R4000SC: @@ -232,11 +233,11 @@ if (!empty_zero_page) panic("Oh boy, that early out of memory?"); - pg = MAP_NR(empty_zero_page); - while (pg < MAP_NR(empty_zero_page) + (1 << order)) { - set_bit(PG_reserved, &mem_map[pg].flags); - set_page_count(mem_map + pg, 0); - pg++; + page = virt_to_page(empty_zero_page); + while (page < virt_to_page(empty_zero_page + (PAGE_SIZE << order))) { + set_bit(PG_reserved, &page->flags); + set_page_count(page, 0); + page++; } size = PAGE_SIZE << order; @@ -374,8 +375,8 @@ void free_initrd_mem(unsigned long start, unsigned long end) { for (; start < end; start += PAGE_SIZE) { - ClearPageReserved(mem_map + MAP_NR(start)); - set_page_count(mem_map+MAP_NR(start), 1); + ClearPageReserved(virt_to_page(start)); + set_page_count(virt_to_page(start), 1); free_page(start); totalram_pages++; } @@ -396,8 +397,8 @@ addr = (unsigned long)(&__init_begin); while (addr < (unsigned long)&__init_end) { page = PAGE_OFFSET | CPHYSADDR(addr); - ClearPageReserved(mem_map + MAP_NR(page)); - set_page_count(mem_map + MAP_NR(page), 1); + ClearPageReserved(virt_to_page(page)); + set_page_count(virt_to_page(page), 1); free_page(page); totalram_pages++; addr += PAGE_SIZE; diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/mm/loadmmu.c linux/arch/mips64/mm/loadmmu.c --- v2.4.0-test5/linux/arch/mips64/mm/loadmmu.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/mm/loadmmu.c Thu Jul 27 18:36:54 2000 @@ -25,13 +25,17 @@ void (*_copy_page)(void * to, void * from); /* Cache operations. */ -void (*_flush_cache_all)(void); void (*_flush_cache_mm)(struct mm_struct *mm); void (*_flush_cache_range)(struct mm_struct *mm, unsigned long start, unsigned long end); void (*_flush_cache_page)(struct vm_area_struct *vma, unsigned long page); -void (*_flush_cache_sigtramp)(unsigned long addr); void (*_flush_page_to_ram)(struct page * page); + +/* MIPS specific cache operations */ +void (*_flush_cache_sigtramp)(unsigned long addr); +void (*_flush_cache_l2)(void); +void (*_flush_cache_l1)(void); + /* DMA cache operations. */ void (*_dma_cache_wback_inv)(unsigned long start, unsigned long size); diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/mm/r4xx0.c linux/arch/mips64/mm/r4xx0.c --- v2.4.0-test5/linux/arch/mips64/mm/r4xx0.c Mon Jul 10 16:47:20 2000 +++ linux/arch/mips64/mm/r4xx0.c Sun Aug 6 11:43:17 2000 @@ -1750,7 +1750,7 @@ */ static void r4k_flush_page_to_ram_s16d16i16(struct page * page) { - unsigned long addr = page_address(page) & PAGE_MASK; + unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { #ifdef DEBUG_CACHE @@ -1762,7 +1762,7 @@ static void r4k_flush_page_to_ram_s32d16i16(struct page * page) { - unsigned long addr = page_address(page) & PAGE_MASK; + unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { #ifdef DEBUG_CACHE @@ -1774,7 +1774,7 @@ static void r4k_flush_page_to_ram_s64d16i16(struct page * page) { - unsigned long addr = page_address(page) & PAGE_MASK; + unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { #ifdef DEBUG_CACHE @@ -1786,7 +1786,7 @@ static void r4k_flush_page_to_ram_s128d16i16(struct page * page) { - unsigned long addr = page_address(page) & PAGE_MASK; + unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { #ifdef DEBUG_CACHE @@ -1798,7 +1798,7 @@ static void r4k_flush_page_to_ram_s32d32i32(struct page * page) { - unsigned long addr = page_address(page) & PAGE_MASK; + unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { #ifdef DEBUG_CACHE @@ -1810,7 +1810,7 @@ static void r4k_flush_page_to_ram_s64d32i32(struct page * page) { - unsigned long addr = page_address(page) & PAGE_MASK; + unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { #ifdef DEBUG_CACHE @@ -1822,7 +1822,7 @@ static void r4k_flush_page_to_ram_s128d32i32(struct page * page) { - unsigned long addr = page_address(page) & PAGE_MASK; + unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { #ifdef DEBUG_CACHE @@ -1834,7 +1834,7 @@ static void r4k_flush_page_to_ram_d16i16(struct page * page) { - unsigned long addr = page_address(page) & PAGE_MASK; + unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { unsigned long flags; @@ -1850,7 +1850,7 @@ static void r4k_flush_page_to_ram_d32i32(struct page * page) { - unsigned long addr = page_address(page) & PAGE_MASK; + unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { unsigned long flags; @@ -1882,7 +1882,7 @@ unsigned int flags; if (size >= dcache_size) { - flush_cache_all(); + flush_cache_l1(); } else { /* Workaround for R4600 bug. See comment above. */ __save_and_cli(flags); @@ -1906,7 +1906,7 @@ unsigned long end, a; if (size >= scache_size) { - flush_cache_all(); + flush_cache_l1(); return; } @@ -1926,7 +1926,7 @@ unsigned int flags; if (size >= dcache_size) { - flush_cache_all(); + flush_cache_l1(); } else { /* Workaround for R4600 bug. See comment above. */ __save_and_cli(flags); @@ -1951,7 +1951,7 @@ unsigned long end, a; if (size >= scache_size) { - flush_cache_all(); + flush_cache_l1(); return; } @@ -2146,6 +2146,11 @@ } } +static void +r4k_flush_cache_l2(void) +{ +} + #ifdef DEBUG_TLBUPDATE static unsigned long ehi_debug[NTLB_ENTRIES]; static unsigned long el0_debug[NTLB_ENTRIES]; @@ -2165,6 +2170,12 @@ pte_t *ptep; int idx, pid; + /* + * Handle debugger faulting in for debugee. + */ + if (current->active_mm != vma->vm_mm) + return; + __save_and_cli(flags); pid = (get_entryhi() & 0xff); @@ -2371,7 +2382,7 @@ case 16: _clear_page = r4k_clear_page_d16; _copy_page = r4k_copy_page_d16; - _flush_cache_all = r4k_flush_cache_all_d16i16; + _flush_cache_l1 = r4k_flush_cache_all_d16i16; _flush_cache_mm = r4k_flush_cache_mm_d16i16; _flush_cache_range = r4k_flush_cache_range_d16i16; _flush_cache_page = r4k_flush_cache_page_d16i16; @@ -2389,7 +2400,7 @@ _clear_page = r4k_clear_page_d32; _copy_page = r4k_copy_page_d32; } - _flush_cache_all = r4k_flush_cache_all_d32i32; + _flush_cache_l1 = r4k_flush_cache_all_d32i32; _flush_cache_mm = r4k_flush_cache_mm_d32i32; _flush_cache_range = r4k_flush_cache_range_d32i32; _flush_cache_page = r4k_flush_cache_page_d32i32; @@ -2407,7 +2418,7 @@ case 16: switch(dc_lsize) { case 16: - _flush_cache_all = r4k_flush_cache_all_s16d16i16; + _flush_cache_l1 = r4k_flush_cache_all_s16d16i16; _flush_cache_mm = r4k_flush_cache_mm_s16d16i16; _flush_cache_range = r4k_flush_cache_range_s16d16i16; _flush_cache_page = r4k_flush_cache_page_s16d16i16; @@ -2422,14 +2433,14 @@ case 32: switch(dc_lsize) { case 16: - _flush_cache_all = r4k_flush_cache_all_s32d16i16; + _flush_cache_l1 = r4k_flush_cache_all_s32d16i16; _flush_cache_mm = r4k_flush_cache_mm_s32d16i16; _flush_cache_range = r4k_flush_cache_range_s32d16i16; _flush_cache_page = r4k_flush_cache_page_s32d16i16; _flush_page_to_ram = r4k_flush_page_to_ram_s32d16i16; break; case 32: - _flush_cache_all = r4k_flush_cache_all_s32d32i32; + _flush_cache_l1 = r4k_flush_cache_all_s32d32i32; _flush_cache_mm = r4k_flush_cache_mm_s32d32i32; _flush_cache_range = r4k_flush_cache_range_s32d32i32; _flush_cache_page = r4k_flush_cache_page_s32d32i32; @@ -2442,14 +2453,14 @@ case 64: switch(dc_lsize) { case 16: - _flush_cache_all = r4k_flush_cache_all_s64d16i16; + _flush_cache_l1 = r4k_flush_cache_all_s64d16i16; _flush_cache_mm = r4k_flush_cache_mm_s64d16i16; _flush_cache_range = r4k_flush_cache_range_s64d16i16; _flush_cache_page = r4k_flush_cache_page_s64d16i16; _flush_page_to_ram = r4k_flush_page_to_ram_s64d16i16; break; case 32: - _flush_cache_all = r4k_flush_cache_all_s64d32i32; + _flush_cache_l1 = r4k_flush_cache_all_s64d32i32; _flush_cache_mm = r4k_flush_cache_mm_s64d32i32; _flush_cache_range = r4k_flush_cache_range_s64d32i32; _flush_cache_page = r4k_flush_cache_page_s64d32i32; @@ -2462,14 +2473,14 @@ case 128: switch(dc_lsize) { case 16: - _flush_cache_all = r4k_flush_cache_all_s128d16i16; + _flush_cache_l1 = r4k_flush_cache_all_s128d16i16; _flush_cache_mm = r4k_flush_cache_mm_s128d16i16; _flush_cache_range = r4k_flush_cache_range_s128d16i16; _flush_cache_page = r4k_flush_cache_page_s128d16i16; _flush_page_to_ram = r4k_flush_page_to_ram_s128d16i16; break; case 32: - _flush_cache_all = r4k_flush_cache_all_s128d32i32; + _flush_cache_l1 = r4k_flush_cache_all_s128d32i32; _flush_cache_mm = r4k_flush_cache_mm_s128d32i32; _flush_cache_range = r4k_flush_cache_range_s128d32i32; _flush_cache_page = r4k_flush_cache_page_s128d32i32; @@ -2538,13 +2549,14 @@ _flush_tlb_mm = r4k_flush_tlb_mm; _flush_tlb_range = r4k_flush_tlb_range; _flush_tlb_page = r4k_flush_tlb_page; + _flush_cache_l2 = r4k_flush_cache_l2; update_mmu_cache = r4k_update_mmu_cache; _show_regs = r4k_show_regs; _user_mode = r4k_user_mode; - flush_cache_all(); + flush_cache_l1(); /* * You should never change this register: diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/mm/umap.c linux/arch/mips64/mm/umap.c --- v2.4.0-test5/linux/arch/mips64/mm/umap.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/mm/umap.c Mon Aug 7 21:02:27 2000 @@ -109,10 +109,10 @@ static inline void free_pte(pte_t page) { if (pte_present(page)) { - unsigned long nr = pte_pagenr(page); - if (nr >= max_mapnr || PageReserved(mem_map+nr)) + struct page *ptpage = pte_page(page); + if ((!VALID_PAGE(ptpage)) || PageReserved(ptpage)) return; - __free_page(pte_page(page)); + __free_page(ptpage); if (current->mm->rss <= 0) return; current->mm->rss--; diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/sgi-ip22/ip22-int.c linux/arch/mips64/sgi-ip22/ip22-int.c --- v2.4.0-test5/linux/arch/mips64/sgi-ip22/ip22-int.c Tue May 23 15:31:33 2000 +++ linux/arch/mips64/sgi-ip22/ip22-int.c Fri Aug 4 16:15:37 2000 @@ -53,8 +53,6 @@ * interrupt controllers, without having to do assembly magic. */ -irq_cpustat_t irq_stat [NR_CPUS]; - struct sgi_int2_regs *sgi_i2regs; struct sgi_int3_regs *sgi_i3regs; struct sgi_ioc_ints *ioc_icontrol; @@ -73,8 +71,6 @@ extern void rs_kgdb_hook(int); #endif -unsigned int local_bh_count[NR_CPUS]; -unsigned int local_irq_count[NR_CPUS]; unsigned long spurious_count = 0; /* Local IRQ's are layed out logically like this: diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/sgi-ip22/ip22-setup.c linux/arch/mips64/sgi-ip22/ip22-setup.c --- v2.4.0-test5/linux/arch/mips64/sgi-ip22/ip22-setup.c Mon Jul 10 16:47:20 2000 +++ linux/arch/mips64/sgi-ip22/ip22-setup.c Wed Aug 9 13:46:02 2000 @@ -114,9 +114,9 @@ int __init page_is_ram(unsigned long pagenr) { - if (pagenr < MAP_NR(PAGE_OFFSET + 0x2000UL)) + if ((pagenr< MAP_NR(PAGE_OFFSET + 0x08002000)) + if ((pagenr< 0x08002000) return 1; return 0; } diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/sgi-ip27/ip27-init.c linux/arch/mips64/sgi-ip27/ip27-init.c --- v2.4.0-test5/linux/arch/mips64/sgi-ip27/ip27-init.c Fri Jul 14 12:12:05 2000 +++ linux/arch/mips64/sgi-ip27/ip27-init.c Thu Jul 27 18:36:54 2000 @@ -301,7 +301,8 @@ memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80); memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x100); - flush_cache_all(); + flush_cache_l1(); + flush_cache_l2(); } #endif } @@ -418,7 +419,8 @@ init_mfhi_war(); #endif _flush_tlb_all(); - flush_cache_all(); + flush_cache_l1(); + flush_cache_l2(); start_secondary(); } diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/sgi-ip27/ip27-irq.c linux/arch/mips64/sgi-ip27/ip27-irq.c --- v2.4.0-test5/linux/arch/mips64/sgi-ip27/ip27-irq.c Fri Jul 14 12:12:05 2000 +++ linux/arch/mips64/sgi-ip27/ip27-irq.c Fri Aug 4 16:15:37 2000 @@ -59,16 +59,12 @@ * interrupt controllers, without having to do assembly magic. */ -irq_cpustat_t irq_stat [NR_CPUS]; - extern asmlinkage void ip27_irq(void); extern int irq_to_bus[], irq_to_slot[], bus_to_cpu[]; int (*irq_cannonicalize)(int irq); int intr_connect_level(int cpu, int bit); int intr_disconnect_level(int cpu, int bit); -unsigned int local_bh_count[NR_CPUS]; -unsigned int local_irq_count[NR_CPUS]; unsigned long spurious_count = 0; /* diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/sgi-ip27/ip27-memory.c linux/arch/mips64/sgi-ip27/ip27-memory.c --- v2.4.0-test5/linux/arch/mips64/sgi-ip27/ip27-memory.c Mon Jul 10 16:47:20 2000 +++ linux/arch/mips64/sgi-ip27/ip27-memory.c Thu Jul 27 18:36:54 2000 @@ -170,24 +170,6 @@ } /* - * HACK ALERT - Things do not work if this is not here. Maybe this is - * acting as a pseudocacheflush operation. The write pattern seems to - * be important, writing a 0 does not help. - */ -void setup_test(cnodeid_t node, pfn_t start, pfn_t end) -{ - unsigned long *ptr = __va(start << PAGE_SHIFT); - unsigned long size = 4 * 1024 * 1024; /* 4M L2 caches */ - - while (size) { - size -= sizeof(unsigned long); - *ptr = (0xdeadbeefbabeb000UL|node); - /* *ptr = 0; */ - ptr++; - } -} - -/* * Currently, the intranode memory hole support assumes that each slot * contains at least 32 MBytes of memory. We assume all bootmem data * fits on the first slot. @@ -210,8 +192,7 @@ /* Foll line hack for non discontigmem; remove once discontigmem * becomes the default. */ max_low_pfn = (slot_lastpfn - slot_firstpfn); - if (node != 0) - setup_test(node, slot_freepfn, slot_lastpfn); + /* * Allocate the node data structure on the node first. */ diff -u --recursive --new-file v2.4.0-test5/linux/arch/mips64/tools/offset.c linux/arch/mips64/tools/offset.c --- v2.4.0-test5/linux/arch/mips64/tools/offset.c Fri Jul 14 12:12:06 2000 +++ linux/arch/mips64/tools/offset.c Thu Jul 27 18:36:54 2000 @@ -78,6 +78,7 @@ offset("#define TASK_FLAGS ", struct task_struct, flags); offset("#define TASK_SIGPENDING ", struct task_struct, sigpending); offset("#define TASK_NEED_RESCHED ", struct task_struct, need_resched); + offset("#define TASK_PTRACE ", struct task_struct, ptrace); offset("#define TASK_COUNTER ", struct task_struct, counter); offset("#define TASK_NICE ", struct task_struct, nice); offset("#define TASK_MM ", struct task_struct, mm); diff -u --recursive --new-file v2.4.0-test5/linux/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S --- v2.4.0-test5/linux/arch/ppc/kernel/entry.S Fri Jul 14 12:12:06 2000 +++ linux/arch/ppc/kernel/entry.S Fri Aug 4 16:15:37 2000 @@ -319,16 +319,16 @@ addi r3,r1,STACK_FRAME_OVERHEAD bl do_IRQ b 3b -1: lis r4,softirq_state@ha - addi r4,r4,softirq_state@l +1: lis r4,irq_stat@ha /* &softirq_active for cpu 0 */ + addi r4,r4,irq_stat@l #ifdef CONFIG_SMP /* get processor # */ lwz r3,PROCESSOR(r2) slwi r3,r3,5 add r4,r4,r3 #endif /* CONFIG_SMP */ - lwz r5,0(r4) - lwz r4,4(r4) + lwz r5,0(r4) /* softirq_active */ + lwz r4,4(r4) /* softirq_mask */ and. r5,r5,r4 beq+ 2f bl do_softirq diff -u --recursive --new-file v2.4.0-test5/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c --- v2.4.0-test5/linux/arch/ppc/kernel/irq.c Fri Jul 14 12:12:06 2000 +++ linux/arch/ppc/kernel/irq.c Fri Aug 4 16:15:37 2000 @@ -74,7 +74,6 @@ irq_desc_t irq_desc[NR_IRQS]; int ppc_spurious_interrupts = 0; -irq_cpustat_t irq_stat [NR_CPUS]; struct irqaction *ppc_irq_action[NR_IRQS]; unsigned int ppc_cached_irq_mask[NR_MASK_WORDS]; unsigned int ppc_lost_interrupts[NR_MASK_WORDS]; diff -u --recursive --new-file v2.4.0-test5/linux/arch/ppc/kernel/local_irq.h linux/arch/ppc/kernel/local_irq.h --- v2.4.0-test5/linux/arch/ppc/kernel/local_irq.h Thu Feb 10 17:11:04 2000 +++ linux/arch/ppc/kernel/local_irq.h Fri Aug 4 16:15:37 2000 @@ -15,8 +15,6 @@ extern int ppc_spurious_interrupts; extern int ppc_second_irq; extern struct irqaction *ppc_irq_action[NR_IRQS]; -extern unsigned int ppc_local_bh_count[NR_CPUS]; -extern unsigned int ppc_local_irq_count[NR_CPUS]; extern unsigned int ppc_cached_irq_mask[NR_MASK_WORDS]; extern unsigned int ppc_lost_interrupts[NR_MASK_WORDS]; extern atomic_t ppc_n_lost_interrupts; diff -u --recursive --new-file v2.4.0-test5/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c --- v2.4.0-test5/linux/arch/ppc/kernel/ppc_ksyms.c Thu Jul 27 17:37:59 2000 +++ linux/arch/ppc/kernel/ppc_ksyms.c Fri Aug 4 16:15:37 2000 @@ -78,7 +78,6 @@ EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(disable_irq_nosync); -EXPORT_SYMBOL(irq_stat); #ifdef CONFIG_SMP EXPORT_SYMBOL(kernel_flag); #endif /* CONFIG_SMP */ diff -u --recursive --new-file v2.4.0-test5/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c --- v2.4.0-test5/linux/arch/ppc/mm/init.c Fri Jul 14 12:12:07 2000 +++ linux/arch/ppc/mm/init.c Mon Aug 7 21:02:27 2000 @@ -797,8 +797,8 @@ #define FREESEC(START,END,CNT) do { \ a = (unsigned long)(&START); \ for (; a < (unsigned long)(&END); a += PAGE_SIZE) { \ - clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags); \ - set_page_count(mem_map+MAP_NR(a), 1); \ + clear_bit(PG_reserved, &virt_to_page(a)->flags); \ + set_page_count(virt_to_page(a), 1); \ free_page(a); \ CNT++; \ } \ @@ -865,8 +865,8 @@ void free_initrd_mem(unsigned long start, unsigned long end) { for (; start < end; start += PAGE_SIZE) { - ClearPageReserved(mem_map + MAP_NR(start)); - set_page_count(mem_map+MAP_NR(start), 1); + ClearPageReserved(virt_to_page(start)); + set_page_count(virt_to_page(start), 1); free_page(start); totalram_pages++; } @@ -1187,7 +1187,7 @@ make sure the ramdisk pages aren't reserved. */ if (initrd_start) { for (addr = initrd_start; addr < initrd_end; addr += PAGE_SIZE) - clear_bit(PG_reserved, &mem_map[MAP_NR(addr)].flags); + clear_bit(PG_reserved, &virt_to_page(addr)->flags); } #endif /* CONFIG_BLK_DEV_INITRD */ @@ -1196,17 +1196,17 @@ if ( rtas_data ) for (addr = rtas_data; addr < PAGE_ALIGN(rtas_data+rtas_size) ; addr += PAGE_SIZE) - SetPageReserved(mem_map + MAP_NR(addr)); + SetPageReserved(virt_to_page(addr)); #endif /* defined(CONFIG_ALL_PPC) */ if ( sysmap_size ) for (addr = (unsigned long)sysmap; addr < PAGE_ALIGN((unsigned long)sysmap+sysmap_size) ; addr += PAGE_SIZE) - SetPageReserved(mem_map + MAP_NR(addr)); + SetPageReserved(virt_to_page(addr)); for (addr = PAGE_OFFSET; addr < (unsigned long)end_of_DRAM; addr += PAGE_SIZE) { - if (!PageReserved(mem_map + MAP_NR(addr))) + if (!PageReserved(virt_to_page(addr))) continue; if (addr < (ulong) etext) codepages++; diff -u --recursive --new-file v2.4.0-test5/linux/arch/ppc/vmlinux.lds linux/arch/ppc/vmlinux.lds --- v2.4.0-test5/linux/arch/ppc/vmlinux.lds Tue May 23 15:31:34 2000 +++ linux/arch/ppc/vmlinux.lds Fri Aug 4 11:23:37 2000 @@ -41,6 +41,7 @@ *(.rodata) *(.rodata1) } + .kstrtab : { *(.kstrtab) } .fini : { *(.fini) } =0 .ctors : { *(.ctors) } .dtors : { *(.dtors) } @@ -63,6 +64,10 @@ __start___ex_table = .; __ex_table : { *(__ex_table) } __stop___ex_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + __ksymtab : { *(__ksymtab) } + __stop___ksymtab = .; . = ALIGN(32); .data.cacheline_aligned : { *(.data.cacheline_aligned) } diff -u --recursive --new-file v2.4.0-test5/linux/arch/s390/kernel/entry.S linux/arch/s390/kernel/entry.S --- v2.4.0-test5/linux/arch/s390/kernel/entry.S Fri May 12 14:18:55 2000 +++ linux/arch/s390/kernel/entry.S Fri Aug 4 16:15:37 2000 @@ -193,7 +193,6 @@ */ sysc_lit: - sysc_softirq_state: .long softirq_state sysc_do_signal: .long do_signal sysc_do_softirq: .long do_softirq sysc_schedule: .long schedule @@ -237,17 +236,8 @@ # # check, if bottom-half has to be done # -#ifdef CONFIG_SMP - l %r1,processor(%r9) # get processor index - sll %r1,5 - al %r1,sysc_softirq_state-sysc_lit(%r13) - l %r0,0(%r1) # get softirq_state[cpu].active - n %r0,4(%r1) # and it with softirq_state[cpu].mask -#else - l %r1,sysc_softirq_state-sysc_lit(%r13) - l %r0,0(%r1) # get softirq_state.active - n %r0,4(%r1) # and it with softirq_state.mask -#endif + l %r0,__LC_IRQ_STAT # get softirq_active + n %r0,__LC_IRQ_STAT+4 # and it with softirq_mask jnz sysc_handle_bottom_half # # check, if reschedule is needed @@ -714,7 +704,6 @@ io_do_IRQ: .long do_IRQ io_schedule: .long schedule io_do_signal: .long do_signal - io_softirq_state: .long softirq_state io_do_softirq: .long do_softirq .globl io_int_handler @@ -737,17 +726,8 @@ # # check, if bottom-half has to be done # -#ifdef CONFIG_SMP - l %r1,processor(%r9) # get processor index - sll %r1,5 - al %r1,io_softirq_state-io_lit(%r13) - l %r0,0(%r1) # get softirq_state[cpu].active - n %r0,4(%r1) # and it with softirq_state[cpu].mask -#else - l %r1,io_softirq_state-io_lit(%r13) - l %r0,0(%r1) # get softirq_state.active - n %r0,4(%r1) # and it with softirq_state.mask -#endif + l %r0,__LC_IRQ_STAT # get softirq_active + n %r0,__LC_IRQ_STAT+4 # and it with softirq_mask jnz io_handle_bottom_half io_return_bh: # diff -u --recursive --new-file v2.4.0-test5/linux/arch/s390/kernel/irq.c linux/arch/s390/kernel/irq.c --- v2.4.0-test5/linux/arch/s390/kernel/irq.c Thu Jul 27 17:37:59 2000 +++ linux/arch/s390/kernel/irq.c Fri Aug 4 16:15:37 2000 @@ -143,9 +143,9 @@ printk("\n%s, CPU %d:\n", str, cpu); printk("irq: %d [%d]\n", - atomic_read(&global_irq_count),atomic_read(&S390_lowcore.local_irq_count)); + atomic_read(&global_irq_count),local_irq_count(smp_processor_id())); printk("bh: %d [%d]\n", - atomic_read(&global_bh_count),atomic_read(&S390_lowcore.local_bh_count)); + atomic_read(&global_bh_count),local_bh_count(smp_processor_id())); stack = (unsigned long *) &str; for (i = 40; i ; i--) { unsigned long x = *++stack; @@ -181,7 +181,7 @@ * already executing in one.. */ if (!atomic_read(&global_irq_count)) { - if (atomic_read(&safe_get_cpu_lowcore(cpu).local_bh_count)|| + if (local_bh_count(cpu)|| !atomic_read(&global_bh_count)) break; } @@ -202,7 +202,7 @@ continue; if (atomic_read(&global_irq_lock)) continue; - if (!(atomic_read(&safe_get_cpu_lowcore(cpu).local_bh_count)) + if (!local_bh_count(cpu) && atomic_read(&global_bh_count)) continue; if (!test_and_set_bit(0,&global_irq_lock)) @@ -288,7 +288,7 @@ if (flags & (1 << EFLAGS_I_SHIFT)) { int cpu = smp_processor_id(); __cli(); - if (!atomic_read(&S390_lowcore.local_irq_count)) + if (!in_irq()) get_irqlock(cpu); } } @@ -296,7 +296,7 @@ void __global_sti(void) { - if (!atomic_read(&S390_lowcore.local_irq_count)) + if (!in_irq()) release_irqlock(smp_processor_id()); __sti(); } @@ -320,7 +320,7 @@ retval = 2 + local_enabled; /* check for global flags if we're not in an interrupt */ - if (!atomic_read(&S390_lowcore.local_irq_count)) + if (!in_irq()) { if (local_enabled) retval = 1; diff -u --recursive --new-file v2.4.0-test5/linux/arch/s390/kernel/process.c linux/arch/s390/kernel/process.c --- v2.4.0-test5/linux/arch/s390/kernel/process.c Mon Jul 10 16:47:20 2000 +++ linux/arch/s390/kernel/process.c Fri Aug 4 16:15:37 2000 @@ -64,8 +64,8 @@ wait_psw.mask = _WAIT_PSW_MASK; wait_psw.addr = (unsigned long) &&idle_wakeup | 0x80000000L; while(1) { - if (softirq_state[smp_processor_id()].active & - softirq_state[smp_processor_id()].mask) { + if (softirq_active(smp_processor_id()) & + softirq_mask(smp_processor_id())) { do_softirq(); continue; } diff -u --recursive --new-file v2.4.0-test5/linux/arch/s390/kernel/s390io.c linux/arch/s390/kernel/s390io.c --- v2.4.0-test5/linux/arch/s390/kernel/s390io.c Fri May 12 14:18:55 2000 +++ linux/arch/s390/kernel/s390io.c Fri Aug 4 16:15:37 2000 @@ -621,8 +621,11 @@ // Hopefully bh_count's will get set when we copy the prefix lowcore // structure to other CPI's ( DJB ) - atomic_set(&S390_lowcore.local_bh_count,0); - atomic_set(&S390_lowcore.local_irq_count,0); + softirq_active(smp_processor_id()) = 0; + softirq_mask(smp_processor_id()) = 0; + local_bh_count(smp_processor_id()) = 0; + local_irq_count(smp_processor_id()) = 0; + syscall_count(smp_processor_id()) = 0; asm volatile ("STCK %0" : "=m" (irq_IPL_TOD)); diff -u --recursive --new-file v2.4.0-test5/linux/arch/s390/mm/fault.c linux/arch/s390/mm/fault.c --- v2.4.0-test5/linux/arch/s390/mm/fault.c Fri May 12 14:18:55 2000 +++ linux/arch/s390/mm/fault.c Fri Aug 4 16:15:37 2000 @@ -65,7 +65,7 @@ address = S390_lowcore.trans_exc_code&0x7ffff000; - if (atomic_read(&S390_lowcore.local_irq_count)) + if (in_irq()) die("page fault from irq handler",regs,error_code); tsk = current; diff -u --recursive --new-file v2.4.0-test5/linux/arch/s390/mm/init.c linux/arch/s390/mm/init.c --- v2.4.0-test5/linux/arch/s390/mm/init.c Fri May 12 14:18:55 2000 +++ linux/arch/s390/mm/init.c Mon Aug 7 21:02:27 2000 @@ -351,8 +351,8 @@ addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { - ClearPageReserved(mem_map + MAP_NR(addr)); - set_page_count(mem_map+MAP_NR(addr), 1); + ClearPageReserved(virt_to_page(addr)); + set_page_count(virt_to_page(addr), 1); free_page(addr); totalram_pages++; } @@ -366,8 +366,8 @@ if (start < end) printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { - ClearPageReserved(mem_map + MAP_NR(start)); - set_page_count(mem_map+MAP_NR(start), 1); + ClearPageReserved(virt_to_page(start)); + set_page_count(virt_to_page(start), 1); free_page(start); totalram_pages++; } diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/boot/compressed/Makefile linux/arch/sh/boot/compressed/Makefile --- v2.4.0-test5/linux/arch/sh/boot/compressed/Makefile Thu Jul 27 17:37:59 2000 +++ linux/arch/sh/boot/compressed/Makefile Wed Aug 9 13:59:04 2000 @@ -18,7 +18,7 @@ # # ZIMAGE_OFFSET is the load offset of the compression loader # -ZIMAGE_OFFSET = $(shell printf "0x%8x" $$[0x80000000+0x$(CONFIG_MEMORY_START)+0x200000+0x10000+0x400]) +ZIMAGE_OFFSET = $(shell printf "0x%8x" $$[0x80000000+0x$(CONFIG_MEMORY_START)+0x200000+0x10000]) ZLINKFLAGS = -Ttext $(ZIMAGE_OFFSET) $(ZLDFLAGS) diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/boot/compressed/head.S linux/arch/sh/boot/compressed/head.S --- v2.4.0-test5/linux/arch/sh/boot/compressed/head.S Fri Jun 23 21:55:08 2000 +++ linux/arch/sh/boot/compressed/head.S Wed Aug 9 13:59:04 2000 @@ -10,6 +10,9 @@ .global startup startup: + /* Load initial status register */ + mov.l init_sr, r1 + ldc r1, sr /* First clear BSS */ mov.l end_addr, r1 @@ -20,10 +23,6 @@ cmp/eq r1,r2 bf l1 - /* Load initial status register */ - mov.l init_sr, r1 - ldc r1, sr - /* Set the initial pointer. */ mov.l init_stack_addr, r0 mov.l @r0, r15 @@ -44,7 +43,7 @@ end_addr: .long _end init_sr: - .long 0x50000000 /* Privileged mode, Bank=0, Block=1, I3-I0=0 */ + .long 0x40000000 /* Privileged mode, Bank=0, Block=0, I3-I0=0 */ init_stack_addr: .long stack_start decompress_kernel_addr: diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/config.in linux/arch/sh/config.in --- v2.4.0-test5/linux/arch/sh/config.in Thu Jul 27 17:37:59 2000 +++ linux/arch/sh/config.in Wed Aug 9 13:59:04 2000 @@ -28,12 +28,19 @@ "Generic CONFIG_SH_GENERIC \ SolutionEngine CONFIG_SH_SOLUTION_ENGINE \ Overdrive CONFIG_SH_OVERDRIVE \ - HP600 CONFIG_SH_HP600" Generic + HP600 CONFIG_SH_HP600 \ + CqREEK CONFIG_SH_CQREEK \ + BareCPU CONFIG_SH_UNKNOWN" Generic choice 'Processor type' \ - "SH7708 CONFIG_CPU_SUBTYPE_SH7708 \ + "SH7707 CONFIG_CPU_SUBTYPE_SH7707 \ + SH7708 CONFIG_CPU_SUBTYPE_SH7708 \ SH7709 CONFIG_CPU_SUBTYPE_SH7709 \ SH7750 CONFIG_CPU_SUBTYPE_SH7750" SH7708 +if [ "$CONFIG_CPU_SUBTYPE_SH7707" = "y" ]; then + define_bool CONFIG_CPU_SH3 y + define_bool CONFIG_CPU_SH4 n +fi if [ "$CONFIG_CPU_SUBTYPE_SH7708" = "y" ]; then define_bool CONFIG_CPU_SH3 y define_bool CONFIG_CPU_SH4 n @@ -52,7 +59,6 @@ define_hex CONFIG_MEMORY_START 0c000000 else hex 'Physical memory start address' CONFIG_MEMORY_START 08000000 - hex 'I/O port offset address' CONFIG_IOPORT_START ba000000 fi endmenu @@ -178,6 +184,12 @@ if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256 fi + +if [ "$CONFIG_SH_GENERIC" = "y" -o \ + "$CONFIG_SH_OVERDRIVE" = "y" -o "$CONFIG_SH_SOLUTION_ENGINE" = "y" ]; then + bool 'Heartbeat LED' CONFIG_HEARTBEAT +fi + if [ "$CONFIG_PARPORT" != "n" ]; then dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT if [ "$CONFIG_PRINTER" != "n" ]; then @@ -221,7 +233,8 @@ bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ bool 'Use LinuxSH standard BIOS' CONFIG_SH_STANDARD_BIOS if [ "$CONFIG_SH_STANDARD_BIOS" = "y" ]; then - bool 'GDB Stub kernel debug' CONFIG_DEBUG_KERNEL_WITH_GDB_STUB - bool 'Early printk support' CONFIG_SH_EARLY_PRINTK + hex ' GDB Stub VBR' CONFIG_GDB_STUB_VBR a0000000 + bool 'GDB Stub kernel debug' CONFIG_DEBUG_KERNEL_WITH_GDB_STUB + bool 'Early printk support' CONFIG_SH_EARLY_PRINTK fi endmenu diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/defconfig linux/arch/sh/defconfig --- v2.4.0-test5/linux/arch/sh/defconfig Thu Jul 27 17:37:59 2000 +++ linux/arch/sh/defconfig Wed Aug 9 13:59:04 2000 @@ -21,6 +21,8 @@ # CONFIG_SH_SOLUTION_ENGINE is not set # CONFIG_SH_OVERDRIVE is not set # CONFIG_SH_HP600 is not set +# CONFIG_SH_UNKNOWN is not set +# CONFIG_CPU_SUBTYPE_SH7707 is not set CONFIG_CPU_SUBTYPE_SH7708=y # CONFIG_CPU_SUBTYPE_SH7709 is not set # CONFIG_CPU_SUBTYPE_SH7750 is not set @@ -28,7 +30,6 @@ # CONFIG_CPU_SH4 is not set CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_MEMORY_START=0c000000 -CONFIG_IOPORT_START=ba000000 # # General setup @@ -139,6 +140,7 @@ # Unix 98 PTY support # # CONFIG_UNIX98_PTYS is not set +# CONFIG_HEARTBEAT is not set # # File systems @@ -200,4 +202,5 @@ # CONFIG_MAGIC_SYSRQ is not set CONFIG_SH_STANDARD_BIOS=y CONFIG_DEBUG_KERNEL_WITH_GDB_STUB=y +CONFIG_GDB_STUB_VBR=a0000000 CONFIG_SH_EARLY_PRINTK=y diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/kernel/Makefile linux/arch/sh/kernel/Makefile --- v2.4.0-test5/linux/arch/sh/kernel/Makefile Thu Jul 27 17:37:59 2000 +++ linux/arch/sh/kernel/Makefile Wed Aug 9 13:59:04 2000 @@ -11,8 +11,8 @@ O_TARGET := kernel.o O_OBJS := process.o signal.o entry.o traps.o irq.o irq_ipr.o \ - ptrace.o setup.o time.o sys_sh.o semaphore.o pci-sh.o \ - irq_imask.o + ptrace.o setup.o time.o sys_sh.o semaphore.o \ + irq_imask.o io.o OX_OBJS := sh_ksyms.o MX_OBJS := @@ -21,26 +21,45 @@ endif ifdef CONFIG_SH_GENERIC + +O_OBJS += mach_se.o setup_se.o setup_cqreek.o io_se.o led_se.o \ + mach_hp600.o io_hd64461.o \ + mach_unknown.o io_unknown.o \ + io_generic.o + +else + +ifdef CONFIG_SH_HP600 +O_OBJS += mach_hp600.o io_hd64461.o io_generic.o +endif + +ifdef CONFIG_SH_OVERDRIVE O_OBJS += io_generic.o endif ifdef CONFIG_SH_SOLUTION_ENGINE -O_OBJS += setup_se.o io_se.o +O_OBJS += mach_se.o setup_se.o io_se.o io_generic.o led_se.o endif -ifdef CONFIG_SH_OVERDRIVE -O_OBJS += setup_od.o io_generic.o +ifdef CONFIG_SH_CQREEK +O_OBJS += setup_cqreek.o +endif + +ifdef CONFIG_SH_UNKNOWN +O_OBJS += mach_unknown.o io_unknown.o io_generic.o endif -ifdef CONFIG_SH_HP600 -O_OBJS += io_hd64461.o endif ifdef CONFIG_CPU_SH4 O_OBJS += fpu.o endif -ifdef CONFIG_HD64461 +ifdef CONFIG_PCI +O_OBJS += pci-sh.o +endif + +ifneq ($(CONFIG_SH_GENERIC)$(CONFIG_HD64461),) O_OBJS += setup_hd64461.o endif diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/kernel/cf-enabler.c linux/arch/sh/kernel/cf-enabler.c --- v2.4.0-test5/linux/arch/sh/kernel/cf-enabler.c Thu Jul 27 17:37:59 2000 +++ linux/arch/sh/kernel/cf-enabler.c Wed Aug 9 13:59:04 2000 @@ -14,15 +14,18 @@ #include #include -#ifdef CONFIG_SH_SOLUTION_ENGINE #include + + /* + * SolutionEngine + * * 0xB8400000 : Common Memory * 0xB8500000 : Attribute * 0xB8600000 : I/O */ -int __init cf_init(void) +static int __init cf_init_se(void) { if ((ctrl_inw(MRSHPC_CSR) & 0x000c) != 0) return 0; /* Not detected */ @@ -68,11 +71,15 @@ ctrl_outb(0x42, PA_MRSHPC_MW2 + 0x200); return 0; } -#else /* then generic system type */ + #define CF_CIS_BASE 0xb8000000 /* * You can connect Compact Flash directly to the bus of SuperH. * This is the enabler for that. + * + * SIM: How generic is this really? It looks pretty board, or at + * least SH sub-type, specific to me. + * I know it doesn't work on the Overdrive! */ /* @@ -81,7 +88,7 @@ * 0xBA000000 : I/O */ -int __init cf_init(void) +static int __init cf_init_default(void) { /* Enable the card, and set the level interrupt */ ctrl_outw(0x0042, CF_CIS_BASE+0x0200); @@ -89,6 +96,13 @@ disable_irq(14); return 0; } -#endif + +int __init cf_init(void) +{ + if (MACH_SE) { + return cf_init_se(); + } + return cf_init_default(); +} __initcall (cf_init); diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/kernel/entry.S linux/arch/sh/kernel/entry.S --- v2.4.0-test5/linux/arch/sh/kernel/entry.S Thu Jul 27 17:37:59 2000 +++ linux/arch/sh/kernel/entry.S Wed Aug 9 13:59:04 2000 @@ -62,7 +62,7 @@ #if defined(__sh3__) TRA = 0xffffffd0 EXPEVT = 0xffffffd4 -#ifdef CONFIG_CPU_SUBTYPE_SH7709 +#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) INTEVT = 0xa4000000 ! INTEVTE2(0xa4000000) #else INTEVT = 0xffffffd8 @@ -182,7 +182,7 @@ 1: .long SYMBOL_NAME(do_page_fault) 2: .long MMU_TEA -#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB +#if defined(CONFIG_DEBUG_KERNEL_WITH_GDB_STUB) || defined(CONFIG_SH_STANDARD_BIOS) .align 2 /* Unwind the stack and jmp to the debug entry */ debug_kernel: @@ -219,12 +219,12 @@ ldc $k1, $ssr .align 2 1: .long 0x300000f0 -2: .long 0xa0000100 +2: .long CONFIG_GDB_STUB_VBR + 0x100 #endif .align 2 debug_trap: -#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB +#if defined(CONFIG_DEBUG_KERNEL_WITH_GDB_STUB) || defined(CONFIG_SH_STANDARD_BIOS) mov #SR, $r0 mov.l @($r0,$r15), $r0 ! get status register shll $r0 @@ -462,9 +462,9 @@ /* fall through */ ENTRY(ret_from_syscall) - mov.l __softirq_state, $r0 + mov.l __irq_stat, $r0 ! softirq_active mov.l @$r0, $r1 - mov.l @(4,$r0), $r2 + mov.l @(4,$r0), $r2 ! softirq_mask tst $r2, $r1 bt ret_with_reschedule handle_softirq: @@ -489,8 +489,8 @@ .align 2 __do_signal: .long SYMBOL_NAME(do_signal) -__softirq_state: - .long SYMBOL_NAME(softirq_state) +__irq_stat: + .long SYMBOL_NAME(irq_stat) __do_softirq: .long SYMBOL_NAME(do_softirq) @@ -829,7 +829,7 @@ .long SYMBOL_NAME(do_IRQ) ! rovi .long SYMBOL_NAME(do_IRQ) .long SYMBOL_NAME(do_IRQ) -#if defined(CONFIG_CPU_SUBTYPE_SH7709) +#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) .long SYMBOL_NAME(do_IRQ) ! 32 IRQ irq0 .long SYMBOL_NAME(do_IRQ) ! 33 irq1 .long SYMBOL_NAME(do_IRQ) ! 34 irq2 @@ -859,6 +859,11 @@ .long SYMBOL_NAME(do_IRQ) ! 58 bri2 .long SYMBOL_NAME(do_IRQ) ! 59 txi2 .long SYMBOL_NAME(do_IRQ) ! 60 ADC adi +#if defined(CONFIG_CPU_SUBTYPE_SH7707) + .long SYMBOL_NAME(do_IRQ) ! 61 LCDC lcdi + .long SYMBOL_NAME(do_IRQ) ! 62 PCC pcc0i + .long SYMBOL_NAME(do_IRQ) ! 63 pcc1i +#endif #elif defined(__SH4__) .long SYMBOL_NAME(do_IRQ) ! Hitachi UDI .long SYMBOL_NAME(do_IRQ) ! GPIO diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/kernel/io.c linux/arch/sh/kernel/io.c --- v2.4.0-test5/linux/arch/sh/kernel/io.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/io.c Wed Aug 9 13:59:04 2000 @@ -0,0 +1,202 @@ +/* + * linux/arch/sh/kernel/io_generic.c + * + * Copyright (C) 2000 Stuart Menefy + * + * Provide real functions which expand to whatever the header file defined. + * Also definitions of machine independant IO functions. + */ + +#include +#include + +unsigned int _inb(unsigned long port) +{ + return __inb(port); +} + +unsigned int _inw(unsigned long port) +{ + return __inw(port); +} + +unsigned int _inl(unsigned long port) +{ + return __inl(port); +} + +void _outb(unsigned char b, unsigned long port) +{ + __outb(b, port); +} + +void _outw(unsigned short b, unsigned long port) +{ + __outw(b, port); +} + +void _outl(unsigned int b, unsigned long port) +{ + __outl(b, port); +} + +unsigned int _inb_p(unsigned long port) +{ + return __inb_p(port); +} + +unsigned int _inw_p(unsigned long port) +{ + return __inw_p(port); +} + +void _outb_p(unsigned char b, unsigned long port) +{ + __outb_p(b, port); +} + +void _outw_p(unsigned short b, unsigned long port) +{ + __outw_p(b, port); +} + +void _insb(unsigned long port, void *buffer, unsigned long count) +{ + return __insb(port, buffer, count); +} + +void _insw(unsigned long port, void *buffer, unsigned long count) +{ + __insw(port, buffer, count); +} + +void _insl(unsigned long port, void *buffer, unsigned long count) +{ + __insl(port, buffer, count); +} + +void _outsb(unsigned long port, const void *buffer, unsigned long count) +{ + __outsb(port, buffer, count); +} + +void _outsw(unsigned long port, const void *buffer, unsigned long count) +{ + __outsw(port, buffer, count); +} + +void _outsl(unsigned long port, const void *buffer, unsigned long count) +{ + __outsl(port, buffer, count); + +} + +unsigned long ___raw_readb(unsigned long addr) +{ + return __readb(addr); +} + +unsigned long ___raw_readw(unsigned long addr) +{ + return __readw(addr); +} + +unsigned long ___raw_readl(unsigned long addr) +{ + return __readl(addr); +} + +unsigned long _readb(unsigned long addr) +{ + unsigned long r = __readb(addr); + mb(); + return r; +} + +unsigned long _readw(unsigned long addr) +{ + unsigned long r = __readw(addr); + mb(); + return r; +} + +unsigned long _readl(unsigned long addr) +{ + unsigned long r = __readl(addr); + mb(); + return r; +} + +void ___raw_writeb(unsigned char b, unsigned long addr) +{ + __writeb(b, addr); +} + +void ___raw_writew(unsigned short b, unsigned long addr) +{ + __writew(b, addr); +} + +void ___raw_writel(unsigned int b, unsigned long addr) +{ + __writel(b, addr); +} + +void _writeb(unsigned char b, unsigned long addr) +{ + __writeb(b, addr); + mb(); +} + +void _writew(unsigned short b, unsigned long addr) +{ + __writew(b, addr); + mb(); +} + +void _writel(unsigned int b, unsigned long addr) +{ + __writel(b, addr); + mb(); +} + +/* + * Copy data from IO memory space to "real" memory space. + * This needs to be optimized. + */ +void memcpy_fromio(void * to, unsigned long from, unsigned long count) +{ + while (count) { + count--; + *(char *) to = readb(from); + ((char *) to)++; + from++; + } +} + +/* + * Copy data from "real" memory space to IO memory space. + * This needs to be optimized. + */ +void memcpy_toio(unsigned long to, const void * from, unsigned long count) +{ + while (count) { + count--; + writeb(*(char *) from, to); + ((char *) from)++; + to++; + } +} + +/* + * "memset" on IO memory space. + * This needs to be optimized. + */ +void memset_io(unsigned long dst, int c, unsigned long count) +{ + while (count) { + count--; + writeb(c, dst); + dst++; + } +} diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/kernel/io_generic.c linux/arch/sh/kernel/io_generic.c --- v2.4.0-test5/linux/arch/sh/kernel/io_generic.c Thu Jul 27 17:37:59 2000 +++ linux/arch/sh/kernel/io_generic.c Wed Aug 9 13:59:04 2000 @@ -4,7 +4,8 @@ * * Copyright (C) 2000 Niibe Yutaka * - * Generic I/O routine. + * Generic I/O routine. These can be used where a machine specific version + * is not required. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -14,6 +15,7 @@ #include #include +#include #if defined(__sh3__) /* I'm not sure SH7709 has this kind of bug */ @@ -21,19 +23,31 @@ #define DUMMY_READ_AREA6 0xba000000 #endif -#define PORT2ADDR(x) (CONFIG_IOPORT_START+(x)) +#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x)) + +unsigned long generic_io_base; static inline void delay(void) { ctrl_inw(0xa0000000); } -unsigned long inb(unsigned int port) +unsigned long generic_inb(unsigned int port) { return *(volatile unsigned char*)PORT2ADDR(port); } -unsigned long inb_p(unsigned int port) +unsigned long generic_inw(unsigned int port) +{ + return *(volatile unsigned short*)PORT2ADDR(port); +} + +unsigned long generic_inl(unsigned int port) +{ + return *(volatile unsigned long*)PORT2ADDR(port); +} + +unsigned long generic_inb_p(unsigned int port) { unsigned long v = *(volatile unsigned char*)PORT2ADDR(port); @@ -41,23 +55,29 @@ return v; } -unsigned long inw(unsigned int port) +unsigned long generic_inw_p(unsigned int port) { - return *(volatile unsigned short*)PORT2ADDR(port); + unsigned long v = *(volatile unsigned short*)PORT2ADDR(port); + + delay(); + return v; } -unsigned long inl(unsigned int port) +unsigned long generic_inl_p(unsigned int port) { - return *(volatile unsigned long*)PORT2ADDR(port); + unsigned long v = *(volatile unsigned long*)PORT2ADDR(port); + + delay(); + return v; } -void insb(unsigned int port, void *buffer, unsigned long count) +void generic_insb(unsigned int port, void *buffer, unsigned long count) { unsigned char *buf=buffer; while(count--) *buf++=inb(port); } -void insw(unsigned int port, void *buffer, unsigned long count) +void generic_insw(unsigned int port, void *buffer, unsigned long count) { unsigned short *buf=buffer; while(count--) *buf++=inw(port); @@ -66,7 +86,7 @@ #endif } -void insl(unsigned int port, void *buffer, unsigned long count) +void generic_insl(unsigned int port, void *buffer, unsigned long count) { unsigned long *buf=buffer; while(count--) *buf++=inl(port); @@ -75,34 +95,46 @@ #endif } -void outb(unsigned long b, unsigned int port) +void generic_outb(unsigned long b, unsigned int port) { *(volatile unsigned char*)PORT2ADDR(port) = b; } -void outb_p(unsigned long b, unsigned int port) +void generic_outw(unsigned long b, unsigned int port) +{ + *(volatile unsigned short*)PORT2ADDR(port) = b; +} + +void generic_outl(unsigned long b, unsigned int port) +{ + *(volatile unsigned long*)PORT2ADDR(port) = b; +} + +void generic_outb_p(unsigned long b, unsigned int port) { *(volatile unsigned char*)PORT2ADDR(port) = b; delay(); } -void outw(unsigned long b, unsigned int port) +void generic_outw_p(unsigned long b, unsigned int port) { *(volatile unsigned short*)PORT2ADDR(port) = b; + delay(); } -void outl(unsigned long b, unsigned int port) +void generic_outl_p(unsigned long b, unsigned int port) { - *(volatile unsigned long*)PORT2ADDR(port) = b; + *(volatile unsigned long*)PORT2ADDR(port) = b; + delay(); } -void outsb(unsigned int port, const void *buffer, unsigned long count) +void generic_outsb(unsigned int port, const void *buffer, unsigned long count) { const unsigned char *buf=buffer; while(count--) outb(*buf++, port); } -void outsw(unsigned int port, const void *buffer, unsigned long count) +void generic_outsw(unsigned int port, const void *buffer, unsigned long count) { const unsigned short *buf=buffer; while(count--) outw(*buf++, port); @@ -111,11 +143,60 @@ #endif } -void outsl(unsigned int port, const void *buffer, unsigned long count) +void generic_outsl(unsigned int port, const void *buffer, unsigned long count) { const unsigned long *buf=buffer; while(count--) outl(*buf++, port); #ifdef SH3_PCMCIA_BUG_WORKAROUND ctrl_inb (DUMMY_READ_AREA6); #endif +} + +unsigned long generic_readb(unsigned long addr) +{ + return *(volatile unsigned char*)addr; +} + +unsigned long generic_readw(unsigned long addr) +{ + return *(volatile unsigned short*)addr; +} + +unsigned long generic_readl(unsigned long addr) +{ + return *(volatile unsigned long*)addr; +} + +void generic_writeb(unsigned char b, unsigned long addr) +{ + *(volatile unsigned char*)addr = b; +} + +void generic_writew(unsigned short b, unsigned long addr) +{ + *(volatile unsigned short*)addr = b; +} + +void generic_writel(unsigned int b, unsigned long addr) +{ + *(volatile unsigned long*)addr = b; +} + +void * generic_ioremap(unsigned long offset, unsigned long size) +{ + return (void *) P2SEGADDR(offset); +} + +void * generic_ioremap_nocache (unsigned long offset, unsigned long size) +{ + return (void *) P2SEGADDR(offset); +} + +void generic_iounmap(void *addr) +{ +} + +unsigned long generic_isa_port2addr(unsigned long offset) +{ + return offset + generic_io_base; } diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/kernel/io_hd64461.c linux/arch/sh/kernel/io_hd64461.c --- v2.4.0-test5/linux/arch/sh/kernel/io_hd64461.c Fri Jun 23 21:55:08 2000 +++ linux/arch/sh/kernel/io_hd64461.c Wed Aug 9 13:59:04 2000 @@ -10,15 +10,36 @@ static __inline__ unsigned long PORT2ADDR(unsigned long port) { + /* 16550A: HD64461 internal */ + if (0x3f8<=port && port<=0x3ff) + return CONFIG_HD64461_IOBASE + 0x8000 + ((port-0x3f8)<<1); + if (0x2f8<=port && port<=0x2ff) + return CONFIG_HD64461_IOBASE + 0x7000 + ((port-0x2f8)<<1); + +#ifdef CONFIG_HD64461_ENABLER + /* NE2000: HD64461 PCMCIA channel 0 (I/O) */ + if (0x300<=port && port<=0x31f) + return 0xba000000 + port; + + /* ide0: HD64461 PCMCIA channel 1 (memory) */ + /* On HP690, CF in slot 1 is configured as a memory card + device. See CF+ and CompactFlash Specification for the + detail of CF's memory mapped addressing. */ + if (0x1f0<=port && port<=0x1f7) return 0xb5000000 + port; + if (port == 0x3f6) return 0xb50001fe; +#endif + + /* ??? */ + if (port < 0x10000) return 0xa0000000 + port; + /* HD64461 internal devices (0xb0000000) */ - if (port < 0x10000) return CONFIG_HD64461_IOBASE + port; + if (port < 0x20000) return CONFIG_HD64461_IOBASE + port - 0x10000; /* PCMCIA channel 0, I/O (0xba000000) */ - if (port < 0x20000) return 0xba000000 + port - 0x10000; + if (port < 0x30000) return 0xba000000 + port - 0x20000; - /* PCMCIA channel 1, memory (0xb5000000) - SH7709 cannot support I/O card attached to Area 5 */ - if (port < 0x30000) return 0xb5000000 + port - 0x20000; + /* PCMCIA channel 1, memory (0xb5000000) */ + if (port < 0x40000) return 0xb5000000 + port - 0x30000; /* Whole physical address space (0xa0000000) */ return 0xa0000000 + (port & 0x1fffffff); @@ -29,80 +50,80 @@ ctrl_inw(0xa0000000); } -unsigned long inb(unsigned int port) +unsigned long hd64461_inb(unsigned int port) { return *(volatile unsigned char*)PORT2ADDR(port); } -unsigned long inb_p(unsigned int port) +unsigned long hd64461_inb_p(unsigned int port) { unsigned long v = *(volatile unsigned char*)PORT2ADDR(port); delay(); return v; } -unsigned long inw(unsigned int port) +unsigned long hd64461_inw(unsigned int port) { return *(volatile unsigned short*)PORT2ADDR(port); } -unsigned long inl(unsigned int port) +unsigned long hd64461_inl(unsigned int port) { return *(volatile unsigned long*)PORT2ADDR(port); } -void insb(unsigned int port, void *buffer, unsigned long count) +void hd64461_insb(unsigned int port, void *buffer, unsigned long count) { unsigned char *buf=buffer; while(count--) *buf++=inb(port); } -void insw(unsigned int port, void *buffer, unsigned long count) +void hd64461_insw(unsigned int port, void *buffer, unsigned long count) { unsigned short *buf=buffer; while(count--) *buf++=inw(port); } -void insl(unsigned int port, void *buffer, unsigned long count) +void hd64461_insl(unsigned int port, void *buffer, unsigned long count) { unsigned long *buf=buffer; while(count--) *buf++=inl(port); } -void outb(unsigned long b, unsigned int port) +void hd64461_outb(unsigned long b, unsigned int port) { *(volatile unsigned char*)PORT2ADDR(port) = b; } -void outb_p(unsigned long b, unsigned int port) +void hd64461_outb_p(unsigned long b, unsigned int port) { *(volatile unsigned char*)PORT2ADDR(port) = b; delay(); } -void outw(unsigned long b, unsigned int port) +void hd64461_outw(unsigned long b, unsigned int port) { *(volatile unsigned short*)PORT2ADDR(port) = b; } -void outl(unsigned long b, unsigned int port) +void hd64461_outl(unsigned long b, unsigned int port) { *(volatile unsigned long*)PORT2ADDR(port) = b; } -void outsb(unsigned int port, const void *buffer, unsigned long count) +void hd64461_outsb(unsigned int port, const void *buffer, unsigned long count) { const unsigned char *buf=buffer; while(count--) outb(*buf++, port); } -void outsw(unsigned int port, const void *buffer, unsigned long count) +void hd64461_outsw(unsigned int port, const void *buffer, unsigned long count) { const unsigned short *buf=buffer; while(count--) outw(*buf++, port); } -void outsl(unsigned int port, const void *buffer, unsigned long count) +void hd64461_outsl(unsigned int port, const void *buffer, unsigned long count) { const unsigned long *buf=buffer; while(count--) outl(*buf++, port); diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/kernel/io_se.c linux/arch/sh/kernel/io_se.c --- v2.4.0-test5/linux/arch/sh/kernel/io_se.c Fri Jun 23 21:55:08 2000 +++ linux/arch/sh/kernel/io_se.c Wed Aug 9 13:59:04 2000 @@ -56,7 +56,7 @@ printk("bad PC-like io %s for port 0x%x at 0x%08x\n", \ #name, (port), (__u32) __builtin_return_address(0)) -unsigned long inb(unsigned int port) +unsigned long se_inb(unsigned int port) { if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) return *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port); @@ -66,7 +66,7 @@ return (*port2adr(port))&0xff; } -unsigned long inb_p(unsigned int port) +unsigned long se_inb_p(unsigned int port) { unsigned long v; @@ -80,7 +80,7 @@ return v; } -unsigned long inw(unsigned int port) +unsigned long se_inw(unsigned int port) { if (port >= 0x2000 || (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)) @@ -90,13 +90,13 @@ return 0; } -unsigned long inl(unsigned int port) +unsigned long se_inl(unsigned int port) { maybebadio(inl, port); return 0; } -void outb(unsigned long value, unsigned int port) +void se_outb(unsigned long value, unsigned int port) { if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) *(__u8 *)(sh_pcic_io_wbase + port) = value; @@ -106,7 +106,7 @@ *(port2adr(port)) = value; } -void outb_p(unsigned long value, unsigned int port) +void se_outb_p(unsigned long value, unsigned int port) { if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) *(__u8 *)(sh_pcic_io_wbase + port) = value; @@ -117,7 +117,7 @@ delay(); } -void outw(unsigned long value, unsigned int port) +void se_outw(unsigned long value, unsigned int port) { if (port >= 0x2000 || (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)) @@ -126,12 +126,12 @@ maybebadio(outw, port); } -void outl(unsigned long value, unsigned int port) +void se_outl(unsigned long value, unsigned int port) { maybebadio(outl, port); } -void insb(unsigned int port, void *addr, unsigned long count) +void se_insb(unsigned int port, void *addr, unsigned long count) { volatile __u16 *p = port2adr(port); @@ -148,19 +148,19 @@ } } -void insw(unsigned int port, void *addr, unsigned long count) +void se_insw(unsigned int port, void *addr, unsigned long count) { volatile __u16 *p = port2adr(port); while (count--) *((__u16 *) addr)++ = *p; } -void insl(unsigned int port, void *addr, unsigned long count) +void se_insl(unsigned int port, void *addr, unsigned long count) { maybebadio(insl, port); } -void outsb(unsigned int port, const void *addr, unsigned long count) +void se_outsb(unsigned int port, const void *addr, unsigned long count) { volatile __u16 *p = port2adr(port); @@ -177,24 +177,54 @@ } } -void outsw(unsigned int port, const void *addr, unsigned long count) +void se_outsw(unsigned int port, const void *addr, unsigned long count) { volatile __u16 *p = port2adr(port); while (count--) *p = *((__u16 *) addr)++; } -void outsl(unsigned int port, const void *addr, unsigned long count) +void se_outsl(unsigned int port, const void *addr, unsigned long count) { maybebadio(outsw, port); } + +unsigned long se_readb(unsigned long addr) +{ + return *(volatile unsigned char*)addr; +} + +unsigned long se_readw(unsigned long addr) +{ + return *(volatile unsigned short*)addr; +} + +unsigned long se_readl(unsigned long addr) +{ + return *(volatile unsigned long*)addr; +} + +void se_writeb(unsigned char b, unsigned long addr) +{ + *(volatile unsigned char*)addr = b; +} + +void se_writew(unsigned short b, unsigned long addr) +{ + *(volatile unsigned short*)addr = b; +} + +void se_writel(unsigned int b, unsigned long addr) +{ + *(volatile unsigned long*)addr = b; +} /* Map ISA bus address to the real address. Only for PCMCIA. */ /* ISA page descriptor. */ static __u32 sh_isa_memmap[256]; -int +static int sh_isa_mmap(__u32 start, __u32 length, __u32 offset) { int idx; @@ -212,7 +242,7 @@ } unsigned long -sh_isa_slot(unsigned long offset) +se_isa_port2addr(unsigned long offset) { int idx; diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/kernel/io_unknown.c linux/arch/sh/kernel/io_unknown.c --- v2.4.0-test5/linux/arch/sh/kernel/io_unknown.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/io_unknown.c Wed Aug 9 13:59:04 2000 @@ -0,0 +1,47 @@ +/* + * linux/arch/sh/kernel/io_unknown.c + * + * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * I/O routine for unknown hardware. + */ + +static unsigned int unknown_handler(void) +{ + return 0; +} + +#define UNKNOWN_ALIAS(fn) \ + void unknown_##fn(void) __attribute__ ((alias ("unknown_handler"))); + +UNKNOWN_ALIAS(inb) +UNKNOWN_ALIAS(inw) +UNKNOWN_ALIAS(inl) +UNKNOWN_ALIAS(outb) +UNKNOWN_ALIAS(outw) +UNKNOWN_ALIAS(outl) +UNKNOWN_ALIAS(inb_p) +UNKNOWN_ALIAS(inw_p) +UNKNOWN_ALIAS(inl_p) +UNKNOWN_ALIAS(outb_p) +UNKNOWN_ALIAS(outw_p) +UNKNOWN_ALIAS(outl_p) +UNKNOWN_ALIAS(insb) +UNKNOWN_ALIAS(insw) +UNKNOWN_ALIAS(insl) +UNKNOWN_ALIAS(outsb) +UNKNOWN_ALIAS(outsw) +UNKNOWN_ALIAS(outsl) +UNKNOWN_ALIAS(readb) +UNKNOWN_ALIAS(readw) +UNKNOWN_ALIAS(readl) +UNKNOWN_ALIAS(writeb) +UNKNOWN_ALIAS(writew) +UNKNOWN_ALIAS(writel) +UNKNOWN_ALIAS(isa_port2addr) +UNKNOWN_ALIAS(ioremap) +UNKNOWN_ALIAS(ioremap_nocache) +UNKNOWN_ALIAS(iounmap) diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/kernel/irq.c linux/arch/sh/kernel/irq.c --- v2.4.0-test5/linux/arch/sh/kernel/irq.c Thu Jul 27 17:37:59 2000 +++ linux/arch/sh/kernel/irq.c Wed Aug 9 13:59:04 2000 @@ -37,13 +37,6 @@ #include #include -#ifdef CONFIG_HD64461 -#include -#endif - -unsigned int __local_bh_count[NR_CPUS]; -unsigned int __local_irq_count[NR_CPUS]; - /* * Micro-access to controllers is serialized over the whole * system. We never hold this lock when we call the actual @@ -97,6 +90,7 @@ * Generic, controller-independent functions: */ +#if defined(CONFIG_PROC_FS) int get_irq_list(char *buf) { int i, j; @@ -108,7 +102,7 @@ p += sprintf(p, "CPU%d ",j); *p++ = '\n'; - for (i = 0 ; i < NR_IRQS ; i++) { + for (i = 0 ; i < ACTUAL_NR_IRQS ; i++) { action = irq_desc[i].action; if (!action) continue; @@ -123,6 +117,7 @@ } return p - buf; } +#endif /* * This should really return information about whether @@ -183,7 +178,7 @@ { disable_irq_nosync(irq); - if (!__local_irq_count[smp_processor_id()]) { + if (!local_irq_count(smp_processor_id())) { do { barrier(); } while (irq_desc[irq].status & IRQ_INPROGRESS); @@ -246,18 +241,7 @@ "shlr %0\n\t" "add #-16, %0\n\t" :"=z" (irq)); -#if defined(CONFIG_HD64461) - if (irq == CONFIG_HD64461_IRQ) { - unsigned short bit; - unsigned short nirr = inw(HD64461_NIRR); - unsigned short nimr = inw(HD64461_NIMR); - nirr &= ~nimr; - for (bit = 1, irq = 0; irq < 16; bit <<= 1, irq++) - if (nirr & bit) break; - if (irq == 16) irq = CONFIG_HD64461_IRQ; - else irq += HD64461_IRQBASE; - } -#endif + irq = irq_demux(irq); kstat.irqs[cpu][irq]++; desc = irq_desc + irq; @@ -319,7 +303,7 @@ #if 0 __sti(); #endif - if (softirq_state[cpu].active&softirq_state[cpu].mask) + if (softirq_active(cpu)&softirq_mask(cpu)) do_softirq(); return 1; } @@ -333,7 +317,7 @@ int retval; struct irqaction * action; - if (irq >= NR_IRQS) + if (irq >= ACTUAL_NR_IRQS) return -EINVAL; if (!handler) return -EINVAL; @@ -361,7 +345,7 @@ struct irqaction **p; unsigned long flags; - if (irq >= NR_IRQS) + if (irq >= ACTUAL_NR_IRQS) return; spin_lock_irqsave(&irq_controller_lock,flags); @@ -411,7 +395,7 @@ for (i = NR_IRQS-1; i > 0; i--) { if (!irq_desc[i].action) { irq_desc[i].status |= IRQ_AUTODETECT | IRQ_WAITING; - if(irq_desc[i].handler->startup(i)) + if (irq_desc[i].handler->startup(i)) irq_desc[i].status |= IRQ_PENDING; } } @@ -433,7 +417,7 @@ if (!(status & IRQ_AUTODETECT)) continue; - + /* It triggered already - consider it spurious. */ if (!(status & IRQ_WAITING)) { irq_desc[i].status = status & ~IRQ_AUTODETECT; diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/kernel/irq_imask.c linux/arch/sh/kernel/irq_imask.c --- v2.4.0-test5/linux/arch/sh/kernel/irq_imask.c Wed Apr 26 16:34:07 2000 +++ linux/arch/sh/kernel/irq_imask.c Wed Aug 9 13:59:04 2000 @@ -8,6 +8,9 @@ * */ +/* NOTE: Will not work on level 15 */ + + #include #include #include @@ -71,7 +74,7 @@ : "r" (~0xf0), "r" (ip << 4)); } -void disable_imask_irq(unsigned int irq) +static void disable_imask_irq(unsigned int irq) { clear_bit(irq, &imask_mask); if (interrupt_priority < IMASK_PRIORITY - irq) diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/kernel/irq_ipr.c linux/arch/sh/kernel/irq_ipr.c --- v2.4.0-test5/linux/arch/sh/kernel/irq_ipr.c Tue May 23 15:31:34 2000 +++ linux/arch/sh/kernel/irq_ipr.c Wed Aug 9 13:59:04 2000 @@ -21,6 +21,7 @@ #include #include +#include struct ipr_data { unsigned int addr; /* Address of Interrupt Priority Register */ @@ -29,15 +30,8 @@ }; static struct ipr_data ipr_data[NR_IRQS]; -void set_ipr_data(unsigned int irq, unsigned int addr, int pos, int priority) -{ - ipr_data[irq].addr = addr; - ipr_data[irq].shift = pos*4; /* POSition (0-3) x 4 means shift */ - ipr_data[irq].priority = priority; -} - static void enable_ipr_irq(unsigned int irq); -void disable_ipr_irq(unsigned int irq); +static void disable_ipr_irq(unsigned int irq); /* shutdown is same as "disable" */ #define shutdown_ipr_irq disable_ipr_irq @@ -61,7 +55,7 @@ end_ipr_irq }; -void disable_ipr_irq(unsigned int irq) +static void disable_ipr_irq(unsigned int irq) { unsigned long val, flags; unsigned int addr = ipr_data[irq].addr; @@ -90,18 +84,11 @@ restore_flags(flags); } -void make_ipr_irq(unsigned int irq) -{ - disable_irq_nosync(irq); - irq_desc[irq].handler = &ipr_irq_type; - disable_ipr_irq(irq); -} - static void mask_and_ack_ipr(unsigned int irq) { disable_ipr_irq(irq); -#ifdef CONFIG_CPU_SUBTYPE_SH7709 +#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) /* This is needed when we use edge triggered setting */ /* XXX: Is it really needed? */ if (IRQ0_IRQ <= irq && irq <= IRQ5_IRQ) { @@ -118,18 +105,39 @@ enable_ipr_irq(irq); } +void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority) +{ + disable_irq_nosync(irq); + ipr_data[irq].addr = addr; + ipr_data[irq].shift = pos*4; /* POSition (0-3) x 4 means shift */ + ipr_data[irq].priority = priority; + + irq_desc[irq].handler = &ipr_irq_type; + disable_ipr_irq(irq); +} + void __init init_IRQ(void) { - int i; + make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY); + make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY); - for (i = TIMER_IRQ; i < NR_IRQS; i++) { - irq_desc[i].handler = &ipr_irq_type; - } + make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); + make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); + make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); + +#ifdef SCIF_ERI_IRQ + make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); + make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); + make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); +#endif - set_ipr_data(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY); - set_ipr_data(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY); +#ifdef IRDA_ERI_IRQ + make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); + make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); + make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); +#endif -#ifdef CONFIG_CPU_SUBTYPE_SH7709 +#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) /* * Initialize the Interrupt Controller (INTC) * registers to their power on values @@ -161,11 +169,16 @@ * You should set corresponding bits of PFC to "00" * to enable these interrupts. */ - set_ipr_data(IRQ0_IRQ, IRQ0_IRP_ADDR, IRQ0_IRP_POS, IRQ0_PRIORITY); - set_ipr_data(IRQ1_IRQ, IRQ1_IRP_ADDR, IRQ1_IRP_POS, IRQ1_PRIORITY); - set_ipr_data(IRQ2_IRQ, IRQ2_IRP_ADDR, IRQ2_IRP_POS, IRQ2_PRIORITY); - set_ipr_data(IRQ3_IRQ, IRQ3_IRP_ADDR, IRQ3_IRP_POS, IRQ3_PRIORITY); - set_ipr_data(IRQ4_IRQ, IRQ4_IRP_ADDR, IRQ4_IRP_POS, IRQ4_PRIORITY); - set_ipr_data(IRQ5_IRQ, IRQ5_IRP_ADDR, IRQ5_IRP_POS, IRQ5_PRIORITY); -#endif /* CONFIG_CPU_SUBTYPE_SH7709 */ + make_ipr_irq(IRQ0_IRQ, IRQ0_IRP_ADDR, IRQ0_IRP_POS, IRQ0_PRIORITY); + make_ipr_irq(IRQ1_IRQ, IRQ1_IRP_ADDR, IRQ1_IRP_POS, IRQ1_PRIORITY); + make_ipr_irq(IRQ2_IRQ, IRQ2_IRP_ADDR, IRQ2_IRP_POS, IRQ2_PRIORITY); + make_ipr_irq(IRQ3_IRQ, IRQ3_IRP_ADDR, IRQ3_IRP_POS, IRQ3_PRIORITY); + make_ipr_irq(IRQ4_IRQ, IRQ4_IRP_ADDR, IRQ4_IRP_POS, IRQ4_PRIORITY); + make_ipr_irq(IRQ5_IRQ, IRQ5_IRP_ADDR, IRQ5_IRP_POS, IRQ5_PRIORITY); +#endif /* CONFIG_CPU_SUBTYPE_SH7707 || CONFIG_CPU_SUBTYPE_SH7709 */ + + /* Perform the machine specific initialisation */ + if (sh_mv.mv_init_irq != NULL) { + sh_mv.mv_init_irq(); + } } diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/kernel/led_se.c linux/arch/sh/kernel/led_se.c --- v2.4.0-test5/linux/arch/sh/kernel/led_se.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/led_se.c Wed Aug 9 13:59:04 2000 @@ -0,0 +1,67 @@ +/* + * linux/arch/sh/kernel/led_se.c + * + * Copyright (C) 2000 Stuart Menefy + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * This file contains Solution Engine specific LED code. + */ + +#include + +static void mach_led(int position, int value) +{ + volatile unsigned short* p = (volatile unsigned short*)0xb0c00000; + + if (value) { + *p |= (1<<8); + } else { + *p &= ~(1<<8); + } +} + +#ifdef CONFIG_HEARTBEAT + +#include + +/* Cycle the LED's in the clasic Knightrider/Sun pattern */ +void heartbeat_se(void) +{ + static unsigned int cnt = 0, period = 0; + volatile unsigned short* p = (volatile unsigned short*)0xb0c00000; + static unsigned bit = 0, up = 1; + + cnt += 1; + if (cnt < period) { + return; + } + + cnt = 0; + + /* Go through the points (roughly!): + * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110 + */ + period = 110 - ( (300< + +#include +#include + +#include +#include +#include + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_hp600 __initmv = { + mv_name: "HP600", + + mv_nr_irqs: 80, /* HD64461_IRQBASE+16, see hd64461.h */ + + mv_inb: hd64461_inb, + mv_inw: hd64461_inw, + mv_inl: hd64461_inl, + mv_outb: hd64461_outb, + mv_outw: hd64461_outw, + mv_outl: hd64461_outl, + + mv_inb_p: hd64461_inb_p, + mv_inw_p: hd64461_inw, + mv_inl_p: hd64461_inl, + mv_outb_p: hd64461_outb_p, + mv_outw_p: hd64461_outw, + mv_outl_p: hd64461_outl, + + mv_insb: hd64461_insb, + mv_insw: hd64461_insw, + mv_insl: hd64461_insl, + mv_outsb: hd64461_outsb, + mv_outsw: hd64461_outsw, + mv_outsl: hd64461_outsl, + + mv_readb: generic_readb, + mv_readw: generic_readw, + mv_readl: generic_readl, + mv_writeb: generic_writeb, + mv_writew: generic_writew, + mv_writel: generic_writel, + + mv_irq_demux: hd64461_irq_demux, + + mv_hw_hp600: 1, + mv_hw_hd64461: 1, +}; +ALIAS_MV(hp600) diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/kernel/mach_se.c linux/arch/sh/kernel/mach_se.c --- v2.4.0-test5/linux/arch/sh/kernel/mach_se.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/mach_se.c Wed Aug 9 13:59:04 2000 @@ -0,0 +1,80 @@ +/* + * linux/arch/sh/kernel/mach_se.c + * + * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Machine vector for the Hitachi SolutionEngine + */ + +#include + +#include +#include + +#include + +void heartbeat_se(void); +void setup_se(void); +void init_se_IRQ(void); + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_se __initmv = { + mv_name: "SolutionEngine", + +#if defined(__SH4__) + mv_nr_irqs: 48, +#elif defined(CONFIG_CPU_SUBTYPE_SH7708) + mv_nr_irqs: 32, +#elif defined(CONFIG_CPU_SUBTYPE_SH7709) + mv_nr_irqs: 61, +#endif + + mv_inb: se_inb, + mv_inw: se_inw, + mv_inl: se_inl, + mv_outb: se_outb, + mv_outw: se_outw, + mv_outl: se_outl, + + mv_inb_p: se_inb_p, + mv_inw_p: se_inw, + mv_inl_p: se_inl, + mv_outb_p: se_outb_p, + mv_outw_p: se_outw, + mv_outl_p: se_outl, + + mv_insb: se_insb, + mv_insw: se_insw, + mv_insl: se_insl, + mv_outsb: se_outsb, + mv_outsw: se_outsw, + mv_outsl: se_outsl, + + mv_readb: se_readb, + mv_readw: se_readw, + mv_readl: se_readl, + mv_writeb: se_writeb, + mv_writew: se_writew, + mv_writel: se_writel, + + mv_ioremap: generic_ioremap, + mv_ioremap_nocache: generic_ioremap_nocache, + mv_iounmap: generic_iounmap, + + mv_isa_port2addr: se_isa_port2addr, + + mv_init_arch: setup_se, + mv_init_irq: init_se_IRQ, +#ifdef CONFIG_HEARTBEAT + mv_heartbeat: heartbeat_se, +#endif + + mv_hw_se: 1, +}; +ALIAS_MV(se) diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/kernel/mach_unknown.c linux/arch/sh/kernel/mach_unknown.c --- v2.4.0-test5/linux/arch/sh/kernel/mach_unknown.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/mach_unknown.c Wed Aug 9 13:59:04 2000 @@ -0,0 +1,68 @@ +/* + * linux/arch/sh/kernel/mach_unknown.c + * + * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Machine specific code for an unknown machine (internal peripherials only) + */ + +#include + +#include +#include + +#include + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_unknown __initmv = { + mv_name: "Unknown", + +#if defined(__SH4__) + mv_nr_irqs: 48, +#elif defined(CONFIG_CPU_SUBTYPE_SH7708) + mv_nr_irqs: 32, +#elif defined(CONFIG_CPU_SUBTYPE_SH7709) + mv_nr_irqs: 61, +#endif + + mv_inb: unknown_inb, + mv_inw: unknown_inw, + mv_inl: unknown_inl, + mv_outb: unknown_outb, + mv_outw: unknown_outw, + mv_outl: unknown_outl, + + mv_inb_p: unknown_inb_p, + mv_inw_p: unknown_inw_p, + mv_inl_p: unknown_inl_p, + mv_outb_p: unknown_outb_p, + mv_outw_p: unknown_outw_p, + mv_outl_p: unknown_outl_p, + + mv_insb: unknown_insb, + mv_insw: unknown_insw, + mv_insl: unknown_insl, + mv_outsb: unknown_outsb, + mv_outsw: unknown_outsw, + mv_outsl: unknown_outsl, + + mv_readb: unknown_readb, + mv_readw: unknown_readw, + mv_readl: unknown_readl, + mv_writeb: unknown_writeb, + mv_writew: unknown_writew, + mv_writel: unknown_writel, + + mv_ioremap: unknown_ioremap, + mv_ioremap_nocache: unknown_ioremap_nocache, + mv_iounmap: unknown_iounmap, + + mv_isa_port2addr: unknown_isa_port2addr, +}; +ALIAS_MV(unknown) diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/kernel/pci-sh.c linux/arch/sh/kernel/pci-sh.c --- v2.4.0-test5/linux/arch/sh/kernel/pci-sh.c Tue Mar 7 14:32:25 2000 +++ linux/arch/sh/kernel/pci-sh.c Wed Aug 9 13:59:04 2000 @@ -4,9 +4,22 @@ #include #include #include +#include -unsigned long resource_fixup(struct pci_dev * dev, struct resource * res, - unsigned long start, unsigned long size) +void __init pcibios_init(void) { - return start; + if (sh_mv.mv_init_pci != NULL) { + sh_mv.mv_init_pci(); + } } + +/* Haven't done anything here as yet */ +char * __init pcibios_setup(char *str) +{ + return str; +} + +/* We don't have anything here to fixup */ +struct pci_fixup pcibios_fixups[] = { + {0, 0, 0, NULL} +}; diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/kernel/semaphore.c linux/arch/sh/kernel/semaphore.c --- v2.4.0-test5/linux/arch/sh/kernel/semaphore.c Tue Mar 7 14:32:25 2000 +++ linux/arch/sh/kernel/semaphore.c Wed Aug 9 13:59:04 2000 @@ -12,6 +12,8 @@ #include #include +spinlock_t semaphore_wake_lock; + /* * Semaphores are implemented using a two-way counter: * The "count" variable is decremented for each process diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/kernel/setup.c linux/arch/sh/kernel/setup.c --- v2.4.0-test5/linux/arch/sh/kernel/setup.c Thu Jul 27 17:37:59 2000 +++ linux/arch/sh/kernel/setup.c Wed Aug 9 13:59:04 2000 @@ -30,13 +30,16 @@ #endif #include #include +#include #include #include #include #include #include #include +#include #include +#include #ifdef CONFIG_SH_EARLY_PRINTK #include #endif @@ -53,10 +56,18 @@ extern int rd_image_start; /* starting block # of image */ #endif +#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_UNKNOWN) +struct sh_machine_vector sh_mv; +#endif + extern void fpu_init(void); extern int root_mountflags; extern int _text, _etext, _edata, _end; +#define MV_NAME_SIZE 32 + +static struct sh_machine_vector* __init get_mv_byname(const char* name); + /* * This is set up by the setup-routine at boot-time */ @@ -180,8 +191,10 @@ #endif - -static inline void parse_mem_cmdline (char ** cmdline_p) +static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE], + struct sh_machine_vector** mvp, + unsigned long *mv_io_base, + int *mv_mmio_enable) { char c = ' ', *to = command_line, *from = COMMAND_LINE; int len = 0; @@ -208,6 +221,35 @@ memory_end = memory_start + mem_size; } } + if (c == ' ' && !memcmp(from, "sh_mv=", 6)) { + char* mv_end; + char* mv_comma; + int mv_len; + if (to != command_line) + to--; + from += 6; + mv_end = strchr(from, ' '); + if (mv_end == NULL) + mv_end = from + strlen(from); + + mv_comma = strchr(from, ','); + if ((mv_comma != NULL) && (mv_comma < mv_end)) { + int ints[3]; + get_options(mv_comma+1, ARRAY_SIZE(ints), ints); + *mv_io_base = ints[1]; + *mv_mmio_enable = ints[2]; + mv_len = mv_comma - from; + } else { + mv_len = mv_end - from; + } + if (mv_len > (MV_NAME_SIZE-1)) + mv_len = MV_NAME_SIZE-1; + memcpy(mv_name, from, mv_len); + mv_name[mv_len] = '\0'; + from = mv_end; + + *mvp = get_mv_byname(mv_name); + } c = *(from++); if (!c) break; @@ -221,6 +263,10 @@ void __init setup_arch(char **cmdline_p) { + struct sh_machine_vector *mv = NULL; + char mv_name[MV_NAME_SIZE] = ""; + unsigned long mv_io_base = 0; + int mv_mmio_enable = 0; unsigned long bootmap_size; unsigned long start_pfn, max_pfn, max_low_pfn; @@ -248,7 +294,58 @@ data_resource.start = virt_to_bus(&_etext); data_resource.end = virt_to_bus(&_edata)-1; - parse_mem_cmdline(cmdline_p); + parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base, &mv_mmio_enable); + +#ifdef CONFIG_SH_GENERIC + if (mv == NULL) { + extern struct sh_machine_vector mv_unknown; + mv = &mv_unknown; + if (*mv_name != '\0') { + printk("Warning: Unsupported machine %s, using unknown\n", + mv_name); + } + } + sh_mv = *mv; +#endif +#ifdef CONFIG_SH_UNKNOWN + sh_mv = mv_unknown; +#endif + +#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_UNKNOWN) + if (mv_io_base != 0) { + sh_mv.mv_inb = generic_inb; + sh_mv.mv_inw = generic_inw; + sh_mv.mv_inl = generic_inl; + sh_mv.mv_outb = generic_outb; + sh_mv.mv_outw = generic_outw; + sh_mv.mv_outl = generic_outl; + + sh_mv.mv_inb_p = generic_inb_p; + sh_mv.mv_inw_p = generic_inw_p; + sh_mv.mv_inl_p = generic_inl_p; + sh_mv.mv_outb_p = generic_outb_p; + sh_mv.mv_outw_p = generic_outw_p; + sh_mv.mv_outl_p = generic_outl_p; + + sh_mv.mv_insb = generic_insb; + sh_mv.mv_insw = generic_insw; + sh_mv.mv_insl = generic_insl; + sh_mv.mv_outsb = generic_outsb; + sh_mv.mv_outsw = generic_outsw; + sh_mv.mv_outsl = generic_outsl; + + sh_mv.mv_isa_port2addr = generic_isa_port2addr; + generic_io_base = mv_io_base; + } + if (mv_mmio_enable != 0) { + sh_mv.mv_readb = generic_readb; + sh_mv.mv_readw = generic_readw; + sh_mv.mv_readl = generic_readl; + sh_mv.mv_writeb = generic_writeb; + sh_mv.mv_writew = generic_writew; + sh_mv.mv_writel = generic_writel; + } +#endif #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) @@ -358,6 +455,11 @@ #endif #endif + /* Perform the machine specific initialisation */ + if (sh_mv.mv_init_arch != NULL) { + sh_mv.mv_init_arch(); + } + #if defined(__SH4__) /* We already grab/initialized FPU in head.S. Make it consisitent. */ init_task.used_math = 1; @@ -366,10 +468,32 @@ paging_init(); } +struct sh_machine_vector* __init get_mv_byname(const char* name) +{ + extern int strcasecmp(const char *, const char *); + extern long __machvec_start, __machvec_end; + struct sh_machine_vector *all_vecs = + (struct sh_machine_vector *)&__machvec_start; + + int i, n = ((unsigned long)&__machvec_end + - (unsigned long)&__machvec_start)/ + sizeof(struct sh_machine_vector); + + for (i = 0; i < n; ++i) { + struct sh_machine_vector *mv = &all_vecs[i]; + if (mv == NULL) + continue; + if (strcasecmp(name, mv->mv_name) == 0) { + return mv; + } + } + return NULL; +} + /* * Get CPU information for use by the procfs. */ - +#ifdef CONFIG_PROC_FS int get_cpuinfo(char *buffer) { char *p = buffer; @@ -384,6 +508,7 @@ p += sprintf(p, "bogomips\t: %lu.%02lu\n\n", (loops_per_sec+2500)/500000, ((loops_per_sec+2500)/5000) % 100); + p += sprintf(p, "Machine: %s\n", sh_mv.mv_name); #define PRINT_CLOCK(name, value) \ p += sprintf(p, name " clock: %d.%02dMHz\n", \ @@ -395,3 +520,4 @@ return p - buffer; } +#endif diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/kernel/setup_cqreek.c linux/arch/sh/kernel/setup_cqreek.c --- v2.4.0-test5/linux/arch/sh/kernel/setup_cqreek.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/setup_cqreek.c Wed Aug 9 13:59:04 2000 @@ -0,0 +1,224 @@ +/* $Id: setup_cqreek.c,v 1.1 2000/08/05 06:25:23 gniibe Exp $ + * + * arch/sh/kernel/setup_cqreek.c + * + * Copyright (C) 2000 Niibe Yutaka + * + * CqREEK IDE/ISA Bridge Support. + * + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#define BRIDGE_FEATURE 0x0002 + +#define BRIDGE_IDE_CTRL 0x0018 +#define BRIDGE_IDE_INTR_LVL 0x001A +#define BRIDGE_IDE_INTR_MASK 0x001C +#define BRIDGE_IDE_INTR_STAT 0x001E + +#define BRIDGE_ISA_CTRL 0x0028 +#define BRIDGE_ISA_INTR_LVL 0x002A +#define BRIDGE_ISA_INTR_MASK 0x002C +#define BRIDGE_ISA_INTR_STAT 0x002E + +#define IDE_OFFSET 0xA4000000UL +#define ISA_OFFSET 0xA4A00000UL + +static unsigned long cqreek_port2addr(unsigned long port) +{ + if (0x0000<=port && port<=0x0040) + return IDE_OFFSET + port; + if ((0x01f0<=port && port<=0x01f7) || port == 0x03f6) + return IDE_OFFSET + port; + + return ISA_OFFSET + port; +} + +static void disable_cqreek_irq(unsigned int irq) +{ + unsigned long flags; + unsigned short mask; + + save_and_cli(flags); + /* Disable IRQ */ + mask = inw(BRIDGE_ISA_INTR_MASK) & ~(1 << irq); + outw_p(mask, BRIDGE_ISA_INTR_MASK); + restore_flags(flags); +} + +static void enable_cqreek_irq(unsigned int irq) +{ + unsigned long flags; + unsigned short mask; + + save_and_cli(flags); + /* Enable IRQ */ + mask = inw(BRIDGE_ISA_INTR_MASK) | (1 << irq); + outw_p(mask, BRIDGE_ISA_INTR_MASK); + restore_flags(flags); +} + +#define CLEAR_AT_ACCEPT + +static void mask_and_ack_cqreek(unsigned int irq) +{ + inw(BRIDGE_ISA_INTR_STAT); + disable_cqreek_irq(irq); +#ifdef CLEAR_AT_ACCEPT + /* Clear IRQ (it might be edge IRQ) */ + outw_p((1<used_math) { - __copy_to_user(&sc->sc_ownedfp, 0, sizeof(int)); + val = 0; + __copy_to_user(&sc->sc_ownedfp, &val, sizeof(int)); return 0; } - __copy_to_user(&sc->sc_ownedfp, 1, sizeof(int)); + val = 1; + __copy_to_user(&sc->sc_ownedfp, &val, sizeof(int)); /* This will cause a "finit" to be triggered by the next attempted FPU operation by the 'current' process. diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/kernel/time.c linux/arch/sh/kernel/time.c --- v2.4.0-test5/linux/arch/sh/kernel/time.c Thu Jul 27 17:37:59 2000 +++ linux/arch/sh/kernel/time.c Wed Aug 9 13:59:04 2000 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -226,6 +227,11 @@ sh_do_profile(regs->pc); #endif +#ifdef CONFIG_HEARTBEAT + if (sh_mv.mv_heartbeat != NULL) + sh_mv.mv_heartbeat(); +#endif + /* * If we have an externally synchronized Linux clock, then update * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be @@ -441,11 +447,11 @@ tmp = (frqcr & 0x2000) >> 11; tmp |= frqcr & 0x0003; pfc = pfc_table[tmp]; -#ifdef CONFIG_SH_HP600 - master_clock = cpu_clock/6; -#else - master_clock = cpu_clock; -#endif + if (MACH_HP600) { + master_clock = cpu_clock/6; + } else { + master_clock = cpu_clock; + } bus_clock = master_clock/pfc; } #elif defined(__SH4__) diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/lib/Makefile linux/arch/sh/lib/Makefile --- v2.4.0-test5/linux/arch/sh/lib/Makefile Tue Apr 11 15:09:14 2000 +++ linux/arch/sh/lib/Makefile Wed Aug 9 13:59:04 2000 @@ -7,6 +7,6 @@ L_TARGET = lib.a L_OBJS = delay.o memcpy.o memset.o memmove.o memchr.o old-checksum.o \ - checksum.o + checksum.o strcasecmp.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/lib/checksum.S linux/arch/sh/lib/checksum.S --- v2.4.0-test5/linux/arch/sh/lib/checksum.S Tue May 23 15:31:34 2000 +++ linux/arch/sh/lib/checksum.S Wed Aug 9 13:59:04 2000 @@ -185,15 +185,65 @@ mov.l r5,@-r15 mov.l r6,@-r15 + mov #3, r0 ! Check src and dest are equally aligned + mov r4, r1 + and r0, r1 + and r5, r0 + cmp/eq r1, r0 + bf 3f ! Different alignments, use slow version + tst #1,r0 ! Check dest word aligned + bf 3f ! If not, do it the slow way + mov #2,r0 - tst r0,r5 ! Check alignment. + tst r0,r5 ! Check dest alignment. bt 2f ! Jump if alignment is ok. add #-2,r6 ! Alignment uses up two bytes. cmp/pz r6 ! Jump if we had at least two bytes. bt/s 1f clrt bra 4f - add #2,r6 ! $r6 was < 2. Deal with it. + add #2,r6 ! $r6 was < 2. Deal with it. + +3: ! Handle different src and dest alinments. + ! This is not common, so simple byte by byte copy will do. + mov r6, r2 + shlr r6 + tst r6, r6 + bt 4f + clrt +SRC(5: mov.b @r4+,r0 ) +DST( mov.b r0,@r5 ) + add #1, r5 +SRC( mov.b @r4+,r1 ) +DST( mov.b r1,@r5 ) + add #1,r5 + + extu.b r0,r0 + extu.b r1,r1 +#ifdef __LITTLE_ENDIAN__ + shll8 r1 +#else + shll8 r0 +#endif + or r1,r0 + + addc r0,r7 + movt r0 + dt r6 + bf/s 5b + cmp/eq #1,r0 + mov #0,r0 + addc r0, r7 + + mov r2, r0 + tst #1, r0 + bt 7f + bra 5f + clrt + + ! src and dest equally aligned, but to a two byte boundary. + ! Handle first two bytes as a special case + .align 5 SRC(1: mov.w @r4+,r0 ) DST( mov.w r0,@r5 ) add #2,r5 diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/lib/strcasecmp.c linux/arch/sh/lib/strcasecmp.c --- v2.4.0-test5/linux/arch/sh/lib/strcasecmp.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/lib/strcasecmp.c Wed Aug 9 13:59:04 2000 @@ -0,0 +1,26 @@ +/* + * linux/arch/alpha/lib/strcasecmp.c + */ + +#include + + +/* We handle nothing here except the C locale. Since this is used in + only one place, on strings known to contain only 7 bit ASCII, this + is ok. */ + +int strcasecmp(const char *a, const char *b) +{ + int ca, cb; + + do { + ca = *a++ & 0xff; + cb = *b++ & 0xff; + if (ca >= 'A' && ca <= 'Z') + ca += 'a' - 'A'; + if (cb >= 'A' && cb <= 'Z') + cb += 'a' - 'A'; + } while (ca == cb && ca != '\0'); + + return ca - cb; +} diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/mm/Makefile linux/arch/sh/mm/Makefile --- v2.4.0-test5/linux/arch/sh/mm/Makefile Fri Oct 22 13:21:46 1999 +++ linux/arch/sh/mm/Makefile Wed Aug 9 13:59:04 2000 @@ -8,6 +8,6 @@ # Note 2! The CFLAGS definition is now in the main makefile... O_TARGET := mm.o -O_OBJS := init.o fault.o ioremap.o extable.o cache.o +O_OBJS := init.o fault.o extable.o cache.o # ioremap.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/mm/cache.c linux/arch/sh/mm/cache.c --- v2.4.0-test5/linux/arch/sh/mm/cache.c Thu Jul 27 17:37:59 2000 +++ linux/arch/sh/mm/cache.c Wed Aug 9 13:59:04 2000 @@ -207,6 +207,9 @@ * compared the tag of cache and if it's not matched, nothing * will be occurred. (We can avoid flushing other caches.) * + * NOTE: We can use A-bit feature here, because we have valid + * entriy in TLB (at least in UTLB), as dcache_wback_range is + * called before this function is called. */ for (v = start; v < end; v+=L1_CACHE_BYTES) { addr = CACHE_IC_ADDRESS_ARRAY | (v&CACHE_IC_ENTRY_MASK) @@ -225,8 +228,12 @@ */ void flush_icache_range(unsigned long start, unsigned long end) { + unsigned long flags; + + save_and_cli(flags); dcache_wback_range(start, end); icache_purge_range(start, end); + restore_flags(flags); } /* @@ -238,11 +245,6 @@ { unsigned long phys, addr, data, i; - /* - * Alas, we don't know where the virtual address is, - * So, we can't use icache_purge_range(). - */ - /* Physical address of this page */ phys = (pg - mem_map)*PAGE_SIZE + __MEMORY_START; @@ -259,6 +261,30 @@ back_to_P1(); } +/* + * Write back & invalidate the D-cache of the page. + * (To avoid "alias" issues) + */ +void flush_dcache_page(struct page *pg) +{ + unsigned long phys, addr, data, i; + + /* Physical address of this page */ + phys = (pg - mem_map)*PAGE_SIZE + __MEMORY_START; + + jump_to_P2(); + /* Loop all the D-cache */ + for (i=0; ivm_mm, addr, addr+PAGE_SIZE); + pgd_t *dir; + pmd_t *pmd; + pte_t *pte; + pte_t entry; + unsigned long phys; + struct page *pg; + + dir = pgd_offset(vma->vm_mm, addr); + pmd = pmd_offset(dir, addr); + if (pmd_none(*pmd)) + return; + if (pmd_bad(*pmd)) + return; + pte = pte_offset(pmd, addr); + entry = *pte; + if (pte_none(entry) || !pte_present(entry)) + return; + phys = pte_val(entry)&PAGE_MASK; + pg = virt_to_page(__va(phys)); + flush_dcache_page(pg); } /* * After accessing the memory from kernel space (P1-area), we need to - * write back the cache line, to avoid "alias" issues. + * write back the cache line to maintain DMA coherency. * * We search the D-cache to see if we have the entries corresponding to * the page, and if found, write back them. diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/mm/fault.c linux/arch/sh/mm/fault.c --- v2.4.0-test5/linux/arch/sh/mm/fault.c Thu Jul 27 17:37:59 2000 +++ linux/arch/sh/mm/fault.c Wed Aug 9 13:59:04 2000 @@ -115,7 +115,8 @@ * ITLB is not affected by "ldtlb" instruction. * So, we need to flush the entry by ourselves. */ - __flush_tlb_page(mm, address&PAGE_MASK); + if (mm) + __flush_tlb_page(mm, address&PAGE_MASK); #endif update_mmu_cache(NULL, address, entry); } @@ -281,15 +282,14 @@ save_and_cli(flags); #if defined(__SH4__) - if ((vma->vm_flags & VM_SHARED)) { + if (vma && (vma->vm_flags & VM_SHARED)) { + struct page *pg; + pteval = pte_val(pte); pteval &= PAGE_MASK; /* Physicall page address */ - __flush_tlb_phys(vma->vm_mm, pteval); - - /* It would be good we had routine which takes - physical memory as argument */ - flush_cache_page(vma, address&PAGE_MASK); + pg = virt_to_page(__va(pteval)); + flush_dcache_page(pg); } #endif diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/mm/init.c linux/arch/sh/mm/init.c --- v2.4.0-test5/linux/arch/sh/mm/init.c Thu Jul 27 17:37:59 2000 +++ linux/arch/sh/mm/init.c Mon Aug 7 21:02:27 2000 @@ -270,8 +270,8 @@ addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { - ClearPageReserved(mem_map + MAP_NR(addr)); - set_page_count(mem_map+MAP_NR(addr), 1); + ClearPageReserved(virt_to_page(addr)); + set_page_count(virt_to_page(addr), 1); free_page(addr); totalram_pages++; } @@ -283,8 +283,8 @@ { unsigned long p; for (p = start; p < end; p += PAGE_SIZE) { - ClearPageReserved(mem_map + MAP_NR(p)); - set_page_count(mem_map+MAP_NR(p), 1); + ClearPageReserved(virt_to_page(p)); + set_page_count(virt_to_page(p), 1); free_page(p); totalram_pages++; } diff -u --recursive --new-file v2.4.0-test5/linux/arch/sh/vmlinux.lds.S linux/arch/sh/vmlinux.lds.S --- v2.4.0-test5/linux/arch/sh/vmlinux.lds.S Thu Jul 27 17:37:59 2000 +++ linux/arch/sh/vmlinux.lds.S Wed Aug 9 13:59:04 2000 @@ -61,6 +61,9 @@ __initcall_start = .; .initcall.init : { *(.initcall.init) } __initcall_end = .; + __machvec_start = .; + .machvec.init : { *(.machvec.init) } + __machvec_end = .; . = ALIGN(4096); __init_end = .; diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc/config.in linux/arch/sparc/config.in --- v2.4.0-test5/linux/arch/sparc/config.in Mon Jul 10 16:47:20 2000 +++ linux/arch/sparc/config.in Wed Aug 9 13:49:55 2000 @@ -1,10 +1,11 @@ -# $Id: config.in,v 1.98 2000/07/06 01:41:29 davem Exp $ +# $Id: config.in,v 1.100 2000/08/07 18:06:54 anton Exp $ # For a description of the syntax of this configuration file, # see Documentation/kbuild/config-language.txt. # mainmenu_name "Linux/SPARC Kernel Configuration" define_bool CONFIG_UID16 y +define_bool CONFIG_HIGHMEM y mainmenu_option next_comment comment 'Code maturity level options' @@ -85,22 +86,29 @@ bool 'Normal floppy disk support' CONFIG_BLK_DEV_FD -bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD -if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then - tristate ' Linear (append) mode' CONFIG_MD_LINEAR - tristate ' RAID-0 (striping) mode' CONFIG_MD_STRIPED -# tristate ' RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING -# tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5 -fi +tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP +dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET + +#tristate 'Logical volume manager (LVM) support' CONFIG_BLK_DEV_LVM N +#if [ "$CONFIG_BLK_DEV_LVM" != "n" ]; then +# bool ' LVM information in proc filesystem' CONFIG_LVM_PROC_FS Y +#fi + +tristate 'Multiple devices driver support' CONFIG_BLK_DEV_MD +dep_tristate ' Linear (append) mode' CONFIG_MD_LINEAR $CONFIG_BLK_DEV_MD +dep_tristate ' RAID-0 (striping) mode' CONFIG_MD_RAID0 $CONFIG_BLK_DEV_MD +dep_tristate ' RAID-1 (mirroring) mode' CONFIG_MD_RAID1 $CONFIG_BLK_DEV_MD +dep_tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5 $CONFIG_BLK_DEV_MD +#if [ "$CONFIG_MD_LINEAR" = "y" -o "$CONFIG_MD_RAID0" = "y" -o "$CONFIG_MD_RAID1" = "y" -o "$CONFIG_MD_RAID5" = "y" ]; then +# bool ' Boot support' CONFIG_MD_BOOT +# bool ' Auto Detect support' CONFIG_AUTODETECT_RAID +#fi tristate 'RAM disk support' CONFIG_BLK_DEV_RAM if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then int ' Default RAM disk size' CONFIG_BLK_DEV_RAM_SIZE 4096 fi dep_bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK_DEV_RAM - -tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP -tristate 'Network block device support' CONFIG_BLK_DEV_NBD endmenu diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc/defconfig linux/arch/sparc/defconfig --- v2.4.0-test5/linux/arch/sparc/defconfig Thu Jul 27 17:37:59 2000 +++ linux/arch/sparc/defconfig Wed Aug 9 13:49:55 2000 @@ -2,6 +2,7 @@ # Automatically generated make config: don't edit # CONFIG_UID16=y +CONFIG_HIGHMEM=y # # Code maturity level options @@ -108,14 +109,16 @@ # Block devices # CONFIG_BLK_DEV_FD=y -CONFIG_BLK_DEV_MD=y +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m -CONFIG_MD_STRIPED=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID5=m CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_NBD=m # # Networking options diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc/kernel/irq.c linux/arch/sparc/kernel/irq.c --- v2.4.0-test5/linux/arch/sparc/kernel/irq.c Thu Jul 27 17:37:59 2000 +++ linux/arch/sparc/kernel/irq.c Sun Aug 6 11:43:17 2000 @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.105 2000/07/26 01:04:02 davem Exp $ +/* $Id: irq.c,v 1.106 2000/08/05 10:48:40 davem Exp $ * arch/sparc/kernel/irq.c: Interrupt request handling routines. On the * Sparc the IRQ's are basically 'cast in stone' * and you are supposed to probe the prom's device @@ -195,16 +195,9 @@ restore_flags(flags); } -#ifndef CONFIG_SMP -unsigned int __local_bh_count; -unsigned int __local_irq_count; - -#else +#ifdef CONFIG_SMP /* SMP interrupt locking on Sparc. */ -unsigned int __local_bh_count[NR_CPUS]; -unsigned int __local_irq_count[NR_CPUS]; - /* Who has global_irq_lock. */ unsigned char global_irq_holder = NO_PROC_ID; @@ -229,14 +222,14 @@ printk("irq: %d [ ", atomic_read(&global_irq_count)); for (i = 0; i < NR_CPUS; i++) { - printk("%d ", __local_irq_count[i]); + printk("%d ", local_irq_count(i)); } printk("]\n"); printk("bh: %d [ ", (spin_is_locked(&global_bh_lock) ? 1 : 0)); for (i = 0; i < NR_CPUS; i++) { - printk("%d ", __local_bh_count[cpu]); + printk("%d ", local_bh_count(cpu)); } printk("]\n"); @@ -263,7 +256,7 @@ * already executing in one.. */ if (!atomic_read(&global_irq_count)) { - if (__local_bh_count[cpu] || !spin_is_locked(&global_bh_lock)) + if (local_bh_count(cpu) || !spin_is_locked(&global_bh_lock)) break; } @@ -282,7 +275,7 @@ continue; if (spin_is_locked (&global_irq_lock)) continue; - if (!__local_bh_count[cpu] && spin_is_locked(&global_bh_lock)) + if (!local_bh_count(cpu) && spin_is_locked(&global_bh_lock)) continue; if (spin_trylock(&global_irq_lock)) break; @@ -358,7 +351,7 @@ if ((flags & PSR_PIL) != PSR_PIL) { int cpu = smp_processor_id(); __cli(); - if (!__local_irq_count[cpu]) + if (!local_irq_count(cpu)) get_irqlock(cpu); } } @@ -367,7 +360,7 @@ { int cpu = smp_processor_id(); - if (!__local_irq_count[cpu]) + if (!local_irq_count(cpu)) release_irqlock(cpu); __sti(); } @@ -394,7 +387,7 @@ retval = 2 + local_enabled; /* check for global flags if we're not in an interrupt */ - if (!__local_irq_count[smp_processor_id()]) { + if (!local_irq_count(smp_processor_id())) { if (local_enabled) retval = 1; if (global_irq_holder == (unsigned char) smp_processor_id()) diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc/kernel/rtrap.S linux/arch/sparc/kernel/rtrap.S --- v2.4.0-test5/linux/arch/sparc/kernel/rtrap.S Thu Feb 10 17:11:05 2000 +++ linux/arch/sparc/kernel/rtrap.S Sun Aug 6 11:43:17 2000 @@ -1,4 +1,4 @@ -/* $Id: rtrap.S,v 1.54 2000/02/09 11:15:03 davem Exp $ +/* $Id: rtrap.S,v 1.55 2000/08/05 10:48:40 davem Exp $ * rtrap.S: Return from Sparc trap low-level code. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -50,10 +50,10 @@ ret_trap_entry: ld [%curptr + AOFF_task_processor], %l3 sll %l3, 5, %l3 - sethi %hi(C_LABEL(softirq_state)), %l4 + sethi %hi(C_LABEL(irq_stat)), %l4 ! &softirq_active add %l4, %l3, %l4 - ld [%l4 + %lo(C_LABEL(softirq_state))], %g5 - ld [%l4 + %lo(C_LABEL(softirq_state) + 4)], %g4 + ld [%l4 + %lo(C_LABEL(irq_stat))], %g5 ! softirq_active + ld [%l4 + %lo(C_LABEL(irq_stat) + 4)], %g4 ! softirq_mask andcc %g4, %g5, %g0 be C_LABEL(ret_trap_lockless_ipi) nop diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc/kernel/sparc_ksyms.c linux/arch/sparc/kernel/sparc_ksyms.c --- v2.4.0-test5/linux/arch/sparc/kernel/sparc_ksyms.c Fri Jul 14 12:12:07 2000 +++ linux/arch/sparc/kernel/sparc_ksyms.c Sun Aug 6 11:43:17 2000 @@ -1,4 +1,4 @@ -/* $Id: sparc_ksyms.c,v 1.101 2000/07/12 00:25:32 anton Exp $ +/* $Id: sparc_ksyms.c,v 1.102 2000/08/05 10:48:40 davem Exp $ * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -146,8 +146,6 @@ EXPORT_SYMBOL(global_irq_count); EXPORT_SYMBOL(synchronize_irq); #endif -EXPORT_SYMBOL(__local_irq_count); -EXPORT_SYMBOL(__local_bh_count); EXPORT_SYMBOL(udelay); EXPORT_SYMBOL(mstk48t02_regs); diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc/kernel/sun4d_smp.c linux/arch/sparc/kernel/sun4d_smp.c --- v2.4.0-test5/linux/arch/sparc/kernel/sun4d_smp.c Thu Jul 27 17:37:59 2000 +++ linux/arch/sparc/kernel/sun4d_smp.c Mon Aug 7 21:02:27 2000 @@ -298,20 +298,20 @@ } /* Free unneeded trap tables */ - ClearPageReserved(mem_map + MAP_NR(trapbase_cpu1)); - set_page_count(mem_map + MAP_NR(trapbase_cpu1), 1); + ClearPageReserved(virt_to_page(trapbase_cpu1)); + set_page_count(virt_to_page(trapbase_cpu1), 1); free_page((unsigned long)trapbase_cpu1); totalram_pages++; num_physpages++; - ClearPageReserved(mem_map + MAP_NR(trapbase_cpu2)); - set_page_count(mem_map + MAP_NR(trapbase_cpu2), 1); + ClearPageReserved(virt_to_page(trapbase_cpu2)); + set_page_count(virt_to_page(trapbase_cpu2), 1); free_page((unsigned long)trapbase_cpu2); totalram_pages++; num_physpages++; - ClearPageReserved(mem_map + MAP_NR(trapbase_cpu3)); - set_page_count(mem_map + MAP_NR(trapbase_cpu3), 1); + ClearPageReserved(virt_to_page(trapbase_cpu3)); + set_page_count(virt_to_page(trapbase_cpu3), 1); free_page((unsigned long)trapbase_cpu3); totalram_pages++; num_physpages++; diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc/kernel/sun4m_smp.c linux/arch/sparc/kernel/sun4m_smp.c --- v2.4.0-test5/linux/arch/sparc/kernel/sun4m_smp.c Thu Jul 27 17:37:59 2000 +++ linux/arch/sparc/kernel/sun4m_smp.c Mon Aug 7 21:02:27 2000 @@ -279,22 +279,22 @@ /* Free unneeded trap tables */ if (!(cpu_present_map & (1 << 1))) { - ClearPageReserved(mem_map + MAP_NR(trapbase_cpu1)); - set_page_count(mem_map + MAP_NR(trapbase_cpu1), 1); + ClearPageReserved(virt_to_page(trapbase_cpu1)); + set_page_count(virt_to_page(trapbase_cpu1), 1); free_page((unsigned long)trapbase_cpu1); totalram_pages++; num_physpages++; } if (!(cpu_present_map & (1 << 2))) { - ClearPageReserved(mem_map + MAP_NR(trapbase_cpu2)); - set_page_count(mem_map + MAP_NR(trapbase_cpu2), 1); + ClearPageReserved(virt_to_page(trapbase_cpu2)); + set_page_count(virt_to_page(trapbase_cpu2), 1); free_page((unsigned long)trapbase_cpu2); totalram_pages++; num_physpages++; } if (!(cpu_present_map & (1 << 3))) { - ClearPageReserved(mem_map + MAP_NR(trapbase_cpu3)); - set_page_count(mem_map + MAP_NR(trapbase_cpu3), 1); + ClearPageReserved(virt_to_page(trapbase_cpu3)); + set_page_count(virt_to_page(trapbase_cpu3), 1); free_page((unsigned long)trapbase_cpu3); totalram_pages++; num_physpages++; diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc/mm/generic.c linux/arch/sparc/mm/generic.c --- v2.4.0-test5/linux/arch/sparc/mm/generic.c Tue Jan 4 13:57:16 2000 +++ linux/arch/sparc/mm/generic.c Wed Aug 9 13:49:55 2000 @@ -1,4 +1,4 @@ -/* $Id: generic.c,v 1.9 1999/12/27 06:30:03 anton Exp $ +/* $Id: generic.c,v 1.10 2000/08/09 00:00:15 davem Exp $ * generic.c: Generic Sparc mm routines that are not dependent upon * MMU type but are Sparc specific. * @@ -18,14 +18,14 @@ if (pte_none(page)) return; if (pte_present(page)) { - unsigned long nr = pte_pagenr(page); - if (nr >= max_mapnr || PageReserved(mem_map+nr)) + struct page *ptpage = pte_page(page); + if ((!VALID_PAGE(ptpage)) || PageReserved(ptpage)) return; /* * free_page() used to be able to clear swap cache * entries. We may now have to do it manually. */ - free_page_and_swap_cache(mem_map+nr); + free_page_and_swap_cache(ptpage); return; } swap_free(pte_to_swp_entry(page)); diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c --- v2.4.0-test5/linux/arch/sparc/mm/init.c Fri Jul 14 12:12:07 2000 +++ linux/arch/sparc/mm/init.c Wed Aug 9 13:49:55 2000 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.88 2000/07/10 20:56:53 anton Exp $ +/* $Id: init.c,v 1.90 2000/08/09 00:00:15 davem Exp $ * linux/arch/sparc/mm/init.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -51,7 +51,9 @@ extern unsigned int sparc_ramdisk_image; extern unsigned int sparc_ramdisk_size; -unsigned long totalram_pages = 0; +unsigned long highstart_pfn, highend_pfn; +unsigned long totalram_pages; +static unsigned long totalhigh_pages; /* * BAD_PAGE is the page that is used for page faults when linux @@ -79,6 +81,21 @@ PAGE_SHARED)); } +pte_t *kmap_pte; +pgprot_t kmap_prot; + +#define kmap_get_fixed_pte(vaddr) \ + pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)) + +void __init kmap_init(void) +{ + unsigned long pteval; + + /* cache the first kmap pte */ + kmap_pte = kmap_get_fixed_pte(FIX_KMAP_BEGIN); + kmap_prot = __pgprot(SRMMU_ET_PTE | SRMMU_PRIV | SRMMU_CACHE); +} + void show_mem(void) { printk("Mem-info:\n"); @@ -119,22 +136,15 @@ #define DEBUG_BOOTMEM extern unsigned long cmdline_memory_size; +extern unsigned long last_valid_pfn; -unsigned long __init bootmem_init(void) +void __init bootmem_init(void) { - unsigned long bootmap_size, start_pfn, end_pfn; + unsigned long bootmap_size, start_pfn, max_pfn; unsigned long end_of_phys_memory = 0UL; unsigned long bootmap_pfn; int i; - /* - * XXX Limit maximum memory until we implement highmem for sparc. - * The nocache region has taken up some room but I'll rearrange - * the virtual address regions soon - Anton - */ - if (!cmdline_memory_size || cmdline_memory_size > 0x0c000000) - cmdline_memory_size = 0x0c000000; - /* XXX It is a bit ambiguous here, whether we should * XXX treat the user specified mem=xxx as total wanted * XXX physical memory, or as a limit to the upper @@ -181,7 +191,16 @@ bootmap_pfn = start_pfn; - end_pfn = end_of_phys_memory >> PAGE_SHIFT; + max_pfn = end_of_phys_memory >> PAGE_SHIFT; + + max_low_pfn = max_pfn; + highstart_pfn = highend_pfn = max_pfn; + + if (max_low_pfn > (SRMMU_MAXMEM >> PAGE_SHIFT)) { + highstart_pfn = max_low_pfn = (SRMMU_MAXMEM >> PAGE_SHIFT); + printk(KERN_NOTICE "%ldMB HIGHMEM available.\n", + (highend_pfn - highstart_pfn) >> (20-PAGE_SHIFT)); + } #ifdef CONFIG_BLK_DEV_INITRD /* Now have to check initial ramdisk, so that bootmap does not overwrite it */ @@ -205,22 +224,41 @@ #endif /* Initialize the boot-time allocator. */ #ifdef DEBUG_BOOTMEM - prom_printf("init_bootmem(spfn[%lx],bpfn[%lx],epfn[%lx])\n", - start_pfn, bootmap_pfn, end_pfn); + prom_printf("init_bootmem(spfn[%lx],bpfn[%lx],mlpfn[%lx])\n", + start_pfn, bootmap_pfn, max_low_pfn); #endif - bootmap_size = init_bootmem(bootmap_pfn, end_pfn); + bootmap_size = init_bootmem(bootmap_pfn, max_low_pfn); /* Now register the available physical memory with the * allocator. */ for (i = 0; sp_banks[i].num_bytes != 0; i++) { + unsigned long curr_pfn, last_pfn, size; + + curr_pfn = sp_banks[i].base_addr >> PAGE_SHIFT; + if (curr_pfn >= max_low_pfn) + break; + + last_pfn = (sp_banks[i].base_addr + sp_banks[i].num_bytes) >> PAGE_SHIFT; + if (last_pfn > max_low_pfn) + last_pfn = max_low_pfn; + + /* + * .. finally, did all the rounding and playing + * around just make the area go away? + */ + if (last_pfn <= curr_pfn) + continue; + + size = (last_pfn - curr_pfn) << PAGE_SHIFT; + #ifdef DEBUG_BOOTMEM prom_printf("free_bootmem: base[%lx] size[%lx]\n", sp_banks[i].base_addr, - sp_banks[i].num_bytes); + size); #endif free_bootmem(sp_banks[i].base_addr, - sp_banks[i].num_bytes); + size); } /* Reserve the kernel text/data/bss, the bootmem bitmap and initrd. */ @@ -245,10 +283,7 @@ reserve_bootmem(phys_base, (start_pfn << PAGE_SHIFT) - phys_base); reserve_bootmem((bootmap_pfn << PAGE_SHIFT), bootmap_size); -#ifdef DEBUG_BOOTMEM - prom_printf("init_bootmem: return end_pfn[%lx]\n", end_pfn); -#endif - return end_pfn; + last_valid_pfn = max_pfn; } /* @@ -334,8 +369,8 @@ prom_printf("[%p,%p] ", first, last); #endif while (first < last) { - ClearPageReserved(mem_map + MAP_NR(first)); - set_page_count(mem_map + MAP_NR(first), 1); + ClearPageReserved(virt_to_page(first)); + set_page_count(virt_to_page(first), 1); free_page((unsigned long)first); totalram_pages++; num_physpages++; @@ -391,6 +426,25 @@ #endif } +void map_high_region(unsigned long start_pfn, unsigned long end_pfn) +{ + unsigned long tmp; + +#ifdef DEBUG_HIGHMEM + printk("mapping high region %08lx - %08lx\n", start_pfn, end_pfn); +#endif + + for (tmp = start_pfn; tmp < end_pfn; tmp++) { + struct page *page = mem_map + tmp; + + ClearPageReserved(page); + set_bit(PG_highmem, &page->flags); + atomic_set(&page->count, 1); + __free_page(page); + totalhigh_pages++; + } +} + void __init mem_init(void) { int codepages = 0; @@ -401,6 +455,10 @@ unsigned long addr, last; #endif + highmem_start_page = mem_map + highstart_pfn; + /* cache the highmem_mapnr */ + highmem_mapnr = highstart_pfn; + /* Saves us work later. */ memset((void *)&empty_zero_page, 0, PAGE_SIZE); @@ -419,7 +477,7 @@ taint_real_pages(); max_mapnr = last_valid_pfn; - high_memory = __va(last_valid_pfn << PAGE_SHIFT); + high_memory = __va(max_low_pfn << PAGE_SHIFT); #ifdef DEBUG_BOOTMEM prom_printf("mem_init: Calling free_all_bootmem().\n"); @@ -430,6 +488,21 @@ free_unused_mem_map(); #endif + for (i = 0; sp_banks[i].num_bytes != 0; i++) { + unsigned long start_pfn = sp_banks[i].base_addr >> PAGE_SHIFT; + unsigned long end_pfn = (sp_banks[i].base_addr + sp_banks[i].num_bytes) >> PAGE_SHIFT; + + if (end_pfn <= highstart_pfn) + continue; + + if (start_pfn < highstart_pfn) + start_pfn = highstart_pfn; + + map_high_region(start_pfn, end_pfn); + } + + totalram_pages += totalhigh_pages; + codepages = (((unsigned long) &etext) - ((unsigned long)&_start)); codepages = PAGE_ALIGN(codepages) >> PAGE_SHIFT; datapages = (((unsigned long) &edata) - ((unsigned long)&etext)); @@ -437,11 +510,12 @@ initpages = (((unsigned long) &__init_end) - ((unsigned long) &__init_begin)); initpages = PAGE_ALIGN(initpages) >> PAGE_SHIFT; - printk("Memory: %dk available (%dk kernel code, %dk data, %dk init) [%08lx,%08lx]\n", + printk("Memory: %dk available (%dk kernel code, %dk data, %dk init, %ldk highmem) [%08lx,%08lx]\n", nr_free_pages() << (PAGE_SHIFT-10), codepages << (PAGE_SHIFT-10), datapages << (PAGE_SHIFT-10), initpages << (PAGE_SHIFT-10), + totalhigh_pages << (PAGE_SHIFT-10), (unsigned long)PAGE_OFFSET, (last_valid_pfn << PAGE_SHIFT)); /* NOTE NOTE NOTE NOTE @@ -468,7 +542,7 @@ struct page *p; page = addr + phys_base; - p = mem_map + MAP_NR(page); + p = virt_to_page(page); ClearPageReserved(p); set_page_count(p, 1); @@ -485,7 +559,7 @@ if (start < end) printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { - struct page *p = mem_map + MAP_NR(start); + struct page *p = virt_to_page(start); ClearPageReserved(p); set_page_count(p, 1); @@ -501,9 +575,16 @@ val->sharedram = 0; val->freeram = nr_free_pages(); val->bufferram = atomic_read(&buffermem_pages); - - val->totalhigh = 0; - val->freehigh = 0; + val->totalhigh = totalhigh_pages; + val->freehigh = nr_free_highpages(); val->mem_unit = PAGE_SIZE; +} + +void flush_page_to_ram(struct page *page) +{ + unsigned long vaddr; + vaddr = kmap(page); + __flush_page_to_ram(page_address(page)); + kunmap(page); } diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc/mm/io-unit.c linux/arch/sparc/mm/io-unit.c --- v2.4.0-test5/linux/arch/sparc/mm/io-unit.c Thu Feb 10 17:11:05 2000 +++ linux/arch/sparc/mm/io-unit.c Wed Aug 9 13:49:55 2000 @@ -1,4 +1,4 @@ -/* $Id: io-unit.c,v 1.21 2000/02/06 22:55:45 zaitcev Exp $ +/* $Id: io-unit.c,v 1.22 2000/08/09 00:00:15 davem Exp $ * io-unit.c: IO-UNIT specific routines for memory management. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -190,7 +190,7 @@ pmdp = pmd_offset(pgdp, addr); ptep = pte_offset(pmdp, addr); - set_pte(ptep, pte_val(mk_pte(mem_map + MAP_NR(page), dvma_prot))); + set_pte(ptep, pte_val(mk_pte(virt_to_page(page), dvma_prot))); i = ((addr - IOUNIT_DMA_BASE) >> PAGE_SHIFT); diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc/mm/iommu.c linux/arch/sparc/mm/iommu.c --- v2.4.0-test5/linux/arch/sparc/mm/iommu.c Thu Feb 10 17:11:05 2000 +++ linux/arch/sparc/mm/iommu.c Wed Aug 9 13:49:55 2000 @@ -1,4 +1,4 @@ -/* $Id: iommu.c,v 1.19 2000/02/06 22:55:45 zaitcev Exp $ +/* $Id: iommu.c,v 1.20 2000/08/09 00:00:15 davem Exp $ * iommu.c: IOMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -247,7 +247,7 @@ pmdp = pmd_offset(pgdp, addr); ptep = pte_offset(pmdp, addr); - set_pte(ptep, mk_pte(mem_map + MAP_NR(page), dvma_prot)); + set_pte(ptep, mk_pte(virt_to_page(page), dvma_prot)); if (ipte_cache != 0) { iopte_val(*iopte++) = MKIOPTE(__pa(page)); } else { diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c --- v2.4.0-test5/linux/arch/sparc/mm/srmmu.c Fri Jul 14 12:12:07 2000 +++ linux/arch/sparc/mm/srmmu.c Wed Aug 9 13:49:56 2000 @@ -1,4 +1,4 @@ -/* $Id: srmmu.c,v 1.218 2000/07/10 23:22:32 anton Exp $ +/* $Id: srmmu.c,v 1.220 2000/08/09 00:00:15 davem Exp $ * srmmu.c: SRMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -87,7 +87,7 @@ ctxd_t *srmmu_ctx_table_phys; ctxd_t *srmmu_context_table; -int viking_mxcc_present = 0; +int viking_mxcc_present; spinlock_t srmmu_context_spinlock = SPIN_LOCK_UNLOCKED; int is_hypersparc; @@ -117,10 +117,6 @@ int srmmu_cache_pagetables; /* XXX Make this dynamic based on ram size - Anton */ -#define SRMMU_NOCACHE_NPAGES 256 -#define SRMMU_NOCACHE_VADDR 0xfc000000 -#define SRMMU_NOCACHE_SIZE (SRMMU_NOCACHE_NPAGES*PAGE_SIZE) -#define SRMMU_NOCACHE_END (SRMMU_NOCACHE_VADDR + SRMMU_NOCACHE_SIZE) #define SRMMU_NOCACHE_BITMAP_SIZE (SRMMU_NOCACHE_NPAGES * 16) #define SRMMU_NOCACHE_BITMAP_SHIFT (PAGE_SHIFT - 4) @@ -616,7 +612,7 @@ static void srmmu_get_task_struct(struct task_struct *tsk) { - atomic_inc(&mem_map[MAP_NR(tsk)].count); + atomic_inc(&virt_to_page(tsk)->count); } /* tsunami.S */ @@ -1190,9 +1186,11 @@ { int i, cpunode; char node_str[128]; - unsigned long end_pfn; + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; - sparc_iomap.start = 0xfd000000; /* 16MB of IOSPACE on all sun4m's. */ + sparc_iomap.start = SUN4M_IOBASE_VADDR; /* 16MB of IOSPACE on all sun4m's. */ if (sparc_cpu_model == sun4d) num_contexts = 65536; /* We know it is Viking */ @@ -1215,7 +1213,7 @@ prom_halt(); } - last_valid_pfn = end_pfn = bootmem_init(); + bootmem_init(); srmmu_nocache_init(); srmmu_inherit_prom_mappings(0xfe400000,(LINUX_OPPROM_ENDVM-PAGE_SIZE)); @@ -1238,6 +1236,14 @@ srmmu_allocate_ptable_skeleton(DVMA_VADDR, DVMA_END); #endif + srmmu_allocate_ptable_skeleton(FIX_KMAP_BEGIN, FIX_KMAP_END); + srmmu_allocate_ptable_skeleton(PKMAP_BASE, PKMAP_BASE_END); + + pgd = pgd_offset_k(PKMAP_BASE); + pmd = pmd_offset(pgd, PKMAP_BASE); + pte = pte_offset(pmd, PKMAP_BASE); + pkmap_page_table = pte; + flush_cache_all(); flush_tlb_all(); @@ -1253,10 +1259,13 @@ sparc_context_init(num_contexts); + kmap_init(); + { unsigned long zones_size[MAX_NR_ZONES] = { 0, 0, 0}; - zones_size[ZONE_DMA] = end_pfn; + zones_size[ZONE_DMA] = max_low_pfn; + zones_size[ZONE_HIGHMEM] = highend_pfn - max_low_pfn; free_area_init(zones_size); } } @@ -2144,7 +2153,7 @@ BTFIXUPSET_CALL(set_pte, srmmu_set_pte, BTFIXUPCALL_SWAPO0O1); BTFIXUPSET_CALL(switch_mm, srmmu_switch_mm, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(pte_pagenr, srmmu_pte_pagenr, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(sparc_pte_pagenr, srmmu_pte_pagenr, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(pmd_page, srmmu_pmd_page, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(pgd_page, srmmu_pgd_page, BTFIXUPCALL_NORM); diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c --- v2.4.0-test5/linux/arch/sparc/mm/sun4c.c Fri Jul 14 12:12:07 2000 +++ linux/arch/sparc/mm/sun4c.c Wed Aug 9 13:49:56 2000 @@ -1,4 +1,4 @@ -/* $Id: sun4c.c,v 1.196 2000/07/07 07:33:11 anton Exp $ +/* $Id: sun4c.c,v 1.197 2000/08/09 00:00:15 davem Exp $ * sun4c.c: Doing in software what should be done in hardware. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -1320,7 +1320,7 @@ unsigned long page; page = ((unsigned long)bufptr) & PAGE_MASK; - if (MAP_NR(page) > max_mapnr) { + if (!VALID_PAGE(virt_to_page(page))) { sun4c_flush_page(page); return (__u32)bufptr; /* already locked */ } @@ -2095,7 +2095,7 @@ static int sun4c_pmd_bad(pmd_t pmd) { return (((pmd_val(pmd) & ~PAGE_MASK) != PGD_TABLE) || - (MAP_NR(pmd_val(pmd)) > max_mapnr)); + (!VALID_PAGE(virt_to_page(pmd_val(pmd))))); } static int sun4c_pmd_present(pmd_t pmd) @@ -2650,7 +2650,7 @@ BTFIXUPSET_CALL(set_pte, sun4c_set_pte, BTFIXUPCALL_STO1O0); - BTFIXUPSET_CALL(pte_pagenr, sun4c_pte_pagenr, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(sparc_pte_pagenr, sun4c_pte_pagenr, BTFIXUPCALL_NORM); #if PAGE_SHIFT <= 12 BTFIXUPSET_CALL(pmd_page, sun4c_pmd_page, BTFIXUPCALL_ANDNINT(PAGE_SIZE - 1)); #else diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/config.in linux/arch/sparc64/config.in --- v2.4.0-test5/linux/arch/sparc64/config.in Fri Jul 14 12:12:07 2000 +++ linux/arch/sparc64/config.in Fri Aug 4 18:16:11 2000 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.117 2000/07/10 20:57:35 davem Exp $ +# $Id: config.in,v 1.119 2000/08/02 10:45:03 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -67,6 +67,7 @@ dep_tristate ' Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT if [ "$CONFIG_PCI" = "y" ]; then tristate 'SUNW, envctrl support' CONFIG_ENVCTRL + tristate '7-Segment Display support' CONFIG_DISPLAY7SEG fi endmenu @@ -199,6 +200,28 @@ endmenu source drivers/fc4/Config.in + +if [ "$CONFIG_PCI" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then + mainmenu_option next_comment + comment 'IEEE 1394 (FireWire) support' + + dep_tristate 'IEEE 1394 (FireWire) support (EXPERIMENTAL)' CONFIG_IEEE1394 $CONFIG_PCI + + if [ "$CONFIG_IEEE1394" != "n" ]; then + dep_tristate 'Texas Instruments PCILynx support' CONFIG_IEEE1394_PCILYNX $CONFIG_IEEE1394 + if [ "$CONFIG_IEEE1394_PCILYNX" != "n" ]; then + bool ' Use PCILynx local RAM' CONFIG_IEEE1394_PCILYNX_LOCALRAM + bool ' Support for non-IEEE1394 local ports' CONFIG_IEEE1394_PCILYNX_PORTS + fi + + dep_tristate 'OHCI (Open Host Controller Interface) support' CONFIG_IEEE1394_OHCI1394 $CONFIG_IEEE1394 + + dep_tristate 'Raw IEEE1394 I/O support' CONFIG_IEEE1394_RAWIO $CONFIG_IEEE1394 + + bool 'Excessive debugging output' CONFIG_IEEE1394_VERBOSEDEBUG + fi + endmenu +fi if [ "$CONFIG_NET" = "y" ]; then mainmenu_option next_comment diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig --- v2.4.0-test5/linux/arch/sparc64/defconfig Thu Jul 27 17:37:59 2000 +++ linux/arch/sparc64/defconfig Fri Aug 4 18:16:11 2000 @@ -65,6 +65,7 @@ CONFIG_PARPORT_1284=y CONFIG_PRINTER=m CONFIG_ENVCTRL=m +CONFIG_DISPLAY7SEG=m # # Console drivers @@ -321,6 +322,17 @@ # CONFIG_SCSI_PLUTO=m CONFIG_SCSI_FCAL=m + +# +# IEEE 1394 (FireWire) support +# +CONFIG_IEEE1394=m +CONFIG_IEEE1394_PCILYNX=m +# CONFIG_IEEE1394_PCILYNX_LOCALRAM is not set +# CONFIG_IEEE1394_PCILYNX_PORTS is not set +CONFIG_IEEE1394_OHCI1394=m +CONFIG_IEEE1394_RAWIO=m +# CONFIG_IEEE1394_VERBOSEDEBUG is not set # # Network device support diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/kernel/Makefile linux/arch/sparc64/kernel/Makefile --- v2.4.0-test5/linux/arch/sparc64/kernel/Makefile Thu Jul 27 17:37:59 2000 +++ linux/arch/sparc64/kernel/Makefile Wed Aug 9 13:49:56 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.60 2000/07/16 18:21:24 ecd Exp $ +# $Id: Makefile,v 1.61 2000/08/09 08:25:19 jj Exp $ # Makefile for the linux kernel. # # Note! Dependencies are done automagically by 'make dep', which also @@ -64,7 +64,7 @@ ifneq ($(NEW_GCC),y) CMODEL_CFLAG := -mmedlow else - CMODEL_CFLAG := -mcmodel=medlow + CMODEL_CFLAG := -m64 -mcmodel=medlow endif check_asm: dummy diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/kernel/ebus.c linux/arch/sparc64/kernel/ebus.c --- v2.4.0-test5/linux/arch/sparc64/kernel/ebus.c Tue Apr 11 15:09:14 2000 +++ linux/arch/sparc64/kernel/ebus.c Fri Aug 4 18:16:11 2000 @@ -1,4 +1,4 @@ -/* $Id: ebus.c,v 1.47 2000/03/25 05:18:10 davem Exp $ +/* $Id: ebus.c,v 1.48 2000/08/02 06:22:35 davem Exp $ * ebus.c: PCI to EBus bridge device. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -34,6 +34,9 @@ #ifdef CONFIG_ENVCTRL extern int envctrl_init(void); #endif +#ifdef CONFIG_DISPLAY7SEG +extern int d7s_init(void); +#endif static inline void *ebus_alloc(size_t size) { @@ -383,6 +386,9 @@ #endif #ifdef CONFIG_OBP_FLASH flash_init(); +#endif +#ifdef CONFIG_DISPLAY7SEG + d7s_init(); #endif clock_probe(); power_init(); diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/kernel/entry.S linux/arch/sparc64/kernel/entry.S --- v2.4.0-test5/linux/arch/sparc64/kernel/entry.S Fri Jul 14 12:12:08 2000 +++ linux/arch/sparc64/kernel/entry.S Fri Aug 4 18:16:11 2000 @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.117 2000/07/11 02:21:12 davem Exp $ +/* $Id: entry.S,v 1.118 2000/08/01 00:11:31 davem Exp $ * arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points. * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -980,7 +980,7 @@ .align 32 .globl linux_sparc_syscall32 linux_sparc_syscall32: - /* Direct access to user regs, must faster. */ + /* Direct access to user regs, much faster. */ cmp %g1, NR_SYSCALLS ! IEU1 Group bgeu,pn %xcc, linux_sparc_ni_syscall ! CTI srl %i0, 0, %o0 ! IEU0 @@ -1009,7 +1009,7 @@ .align 32 .globl linux_sparc_syscall, ret_sys_call linux_sparc_syscall: - /* Direct access to user regs, must faster. */ + /* Direct access to user regs, much faster. */ cmp %g1, NR_SYSCALLS ! IEU1 Group bgeu,pn %xcc, linux_sparc_ni_syscall ! CTI mov %i0, %o0 ! IEU0 diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c --- v2.4.0-test5/linux/arch/sparc64/kernel/ioctl32.c Thu Jul 27 17:37:59 2000 +++ linux/arch/sparc64/kernel/ioctl32.c Fri Aug 4 18:16:11 2000 @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.93 2000/07/24 22:43:15 anton Exp $ +/* $Id: ioctl32.c,v 1.96 2000/08/02 06:22:35 davem Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) @@ -72,7 +72,7 @@ #include #include #include - +#include #include #include @@ -3175,6 +3175,9 @@ COMPATIBLE_IOCTL(RTCSET) COMPATIBLE_IOCTL(I2CIOCSADR) COMPATIBLE_IOCTL(I2CIOCGADR) +COMPATIBLE_IOCTL(D7SIOCRD) +COMPATIBLE_IOCTL(D7SIOCWR) +COMPATIBLE_IOCTL(D7SIOCTM) /* Little m */ COMPATIBLE_IOCTL(MTIOCTOP) /* OPENPROMIO, SunOS/Solaris only, the NetBSD one's have @@ -3725,7 +3728,9 @@ int i; if (!additional_ioctls) { additional_ioctls = module_map(PAGE_SIZE); - if (!additional_ioctls) return -ENOMEM; + if (!additional_ioctls) + return -ENOMEM; + memset(additional_ioctls, 0, PAGE_SIZE); } for (i = 0; i < PAGE_SIZE/sizeof(struct ioctl_trans); i++) if (!additional_ioctls[i].cmd) @@ -3773,7 +3778,6 @@ int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp); struct ioctl_trans *t; - lock_kernel(); filp = fget(fd); if(!filp) goto out2; @@ -3801,6 +3805,5 @@ out: fput(filp); out2: - unlock_kernel(); return error; } diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/kernel/irq.c linux/arch/sparc64/kernel/irq.c --- v2.4.0-test5/linux/arch/sparc64/kernel/irq.c Mon Jul 10 16:47:20 2000 +++ linux/arch/sparc64/kernel/irq.c Sun Aug 6 11:43:17 2000 @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.89 2000/06/30 10:18:38 davem Exp $ +/* $Id: irq.c,v 1.91 2000/08/05 10:48:40 davem Exp $ * irq.c: UltraSparc IRQ handling/init/registry. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -548,13 +548,7 @@ restore_flags(flags); } -/* Only uniprocessor needs this IRQ/BH locking depth, on SMP it - * lives in the brlock table for cache reasons. - */ -#ifndef CONFIG_SMP -unsigned int __local_irq_count; -unsigned int __local_bh_count; -#else +#ifdef CONFIG_SMP /* Who has global_irq_lock. */ unsigned char global_irq_holder = NO_PROC_ID; @@ -571,7 +565,7 @@ printk("]\nbh: %d [ ", (spin_is_locked(&global_bh_lock) ? 1 : 0)); for (i = 0; i < smp_num_cpus; i++) - printk("%u ", cpu_data[i].bh_count); + printk("%u ", local_bh_count(i)); printk("]\n"); } @@ -768,10 +762,12 @@ nbp = __bucket(bp->irq_chain); if ((flags & IBF_ACTIVE) != 0) { +#ifdef CONFIG_PCI if ((flags & IBF_DMA_SYNC) != 0) { upa_readl(dma_sync_reg_table[bp->synctab_ent]); upa_readq(pci_dma_wsync); } +#endif if ((flags & IBF_MULTI) == 0) { struct irqaction *ap = bp->irq_info; ap->handler(__irq(bp), ap->dev_id, regs); diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c --- v2.4.0-test5/linux/arch/sparc64/kernel/process.c Fri Jul 14 12:12:08 2000 +++ linux/arch/sparc64/kernel/process.c Fri Aug 4 18:16:11 2000 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.109 2000/07/11 01:38:57 davem Exp $ +/* $Id: process.c,v 1.110 2000/07/28 09:43:39 davem Exp $ * arch/sparc64/kernel/process.c * * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) @@ -524,7 +524,7 @@ } } -void fault_in_user_windows(struct pt_regs *regs) +void fault_in_user_windows(void) { struct thread_struct *t = ¤t->thread; unsigned long window; diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/kernel/rtrap.S linux/arch/sparc64/kernel/rtrap.S --- v2.4.0-test5/linux/arch/sparc64/kernel/rtrap.S Tue Apr 11 15:09:15 2000 +++ linux/arch/sparc64/kernel/rtrap.S Wed Aug 9 13:49:56 2000 @@ -1,4 +1,4 @@ -/* $Id: rtrap.S,v 1.49 2000/03/29 09:55:31 davem Exp $ +/* $Id: rtrap.S,v 1.53 2000/08/06 05:20:35 davem Exp $ * rtrap.S: Preparing for return from trap on Sparc V9. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -40,8 +40,9 @@ __handle_user_windows: wrpr %g0, RTRAP_PSTATE, %pstate call fault_in_user_windows - add %sp, STACK_BIAS + REGWIN_SZ, %g0 - ba,a,pt %xcc, __handle_user_windows_continue + nop + ba,pt %xcc, __handle_user_windows_continue + nop __handle_perfctrs: /* Don't forget to preserve user window invariants. */ wrpr %g0, RTRAP_PSTATE, %pstate @@ -54,9 +55,9 @@ wrpr %g0, RTRAP_PSTATE, %pstate call fault_in_user_windows - add %sp, STACK_BIAS + REGWIN_SZ, %o0 + nop ba,pt %xcc, __handle_perfctrs_continue - nop + nop __handle_userfpu: rd %fprs, %l5 andcc %l5, FPRS_FEF, %g0 @@ -69,18 +70,25 @@ mov %l6, %o3 call do_signal add %sp, STACK_BIAS + REGWIN_SZ, %o1 + clr %l6 + + /* Signal delivery can modify pt_regs tstate, so we must + * reload it. + */ + ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 + sethi %hi(0xf << 20), %l4 + and %l1, %l4, %l4 ba,pt %xcc, __handle_signal_continue - clr %l6 - nop + andn %l1, %l4, %l1 .align 64 .globl rtrap_clr_l6, rtrap rtrap_clr_l6: clr %l6 rtrap: lduw [%g6 + AOFF_task_processor], %l0 - sethi %hi(softirq_state), %l2 - or %l2, %lo(softirq_state), %l2 + sethi %hi(irq_stat), %l2 ! &softirq_active + or %l2, %lo(irq_stat), %l2 ! &softirq_active sllx %l0, 6, %l0 - ldx [%l2 + %l0], %l1 + ldx [%l2 + %l0], %l1 ! softirq_active + softirq_mask srlx %l1, 32, %l2 andcc %l1, %l2, %g0 diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/kernel/signal.c linux/arch/sparc64/kernel/signal.c --- v2.4.0-test5/linux/arch/sparc64/kernel/signal.c Mon Jul 10 16:47:20 2000 +++ linux/arch/sparc64/kernel/signal.c Fri Aug 4 18:16:11 2000 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.52 2000/07/07 04:25:17 davem Exp $ +/* $Id: signal.c,v 1.53 2000/07/30 23:12:24 davem Exp $ * arch/sparc64/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -166,7 +166,6 @@ return; do_sigsegv: - lock_kernel(); do_exit(SIGSEGV); } @@ -254,7 +253,6 @@ return; do_sigsegv: - lock_kernel(); do_exit(SIGSEGV); } @@ -566,10 +564,8 @@ return; sigill: - lock_kernel(); do_exit(SIGILL); sigsegv: - lock_kernel(); do_exit(SIGSEGV); } diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/kernel/signal32.c linux/arch/sparc64/kernel/signal32.c --- v2.4.0-test5/linux/arch/sparc64/kernel/signal32.c Mon Jul 10 16:47:20 2000 +++ linux/arch/sparc64/kernel/signal32.c Sun Aug 6 11:43:17 2000 @@ -1,4 +1,4 @@ -/* $Id: signal32.c,v 1.65 2000/07/07 04:25:17 davem Exp $ +/* $Id: signal32.c,v 1.66 2000/07/27 01:05:15 davem Exp $ * arch/sparc64/kernel/signal32.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -750,7 +750,7 @@ goto sigsegv; if(pte_present(*ptep)) { - unsigned long page = page_address(pte_page(*ptep)); + unsigned long page = (unsigned long) page_address(pte_page(*ptep)); __asm__ __volatile__(" membar #StoreStore @@ -1175,7 +1175,7 @@ goto sigsegv; if(pte_present(*ptep)) { - unsigned long page = page_address(pte_page(*ptep)); + unsigned long page = (unsigned long) page_address(pte_page(*ptep)); __asm__ __volatile__(" membar #StoreStore diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c --- v2.4.0-test5/linux/arch/sparc64/kernel/smp.c Thu Jul 27 17:38:00 2000 +++ linux/arch/sparc64/kernel/smp.c Sun Aug 6 11:43:17 2000 @@ -87,7 +87,6 @@ { int i; - cpu_data[id].bh_count = 0; /* multiplier and counter set by smp_setup_percpu_timer() */ cpu_data[id].udelay_val = loops_per_sec; @@ -818,14 +817,14 @@ size = PAGE_ALIGN(size); found = size; - base = page_address(p); + base = (unsigned long) page_address(p); while(found != 0) { /* Failure. */ if(p >= (mem_map + max_mapnr)) return 0UL; if(PageReserved(p)) { found = size; - base = page_address(p); + base = (unsigned long) page_address(p); } else { found -= PAGE_SIZE; } diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c --- v2.4.0-test5/linux/arch/sparc64/kernel/sparc64_ksyms.c Mon Jul 10 16:47:20 2000 +++ linux/arch/sparc64/kernel/sparc64_ksyms.c Sun Aug 6 11:43:17 2000 @@ -1,4 +1,4 @@ -/* $Id: sparc64_ksyms.c,v 1.86 2000/06/30 10:18:38 davem Exp $ +/* $Id: sparc64_ksyms.c,v 1.91 2000/08/05 13:30:33 davem Exp $ * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -65,7 +65,6 @@ extern __kernel_size_t __strlen(const char *); extern __kernel_size_t strlen(const char *); extern char saved_command_line[]; -extern char *getname32(u32 name); extern void linux_sparc_syscall(void); extern void rtrap(void); extern void show_regs(struct pt_regs *); @@ -84,6 +83,7 @@ extern int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *)); extern int unregister_ioctl32_conversion(unsigned int cmd); extern int io_remap_page_range(unsigned long from, unsigned long offset, unsigned long size, pgprot_t prot, int space); +extern void __flush_dcache_page(void *addr); extern int __ashrdi3(int, int); @@ -156,9 +156,6 @@ EXPORT_SYMBOL(_do_write_unlock); #endif -#else -EXPORT_SYMBOL(__local_bh_count); -EXPORT_SYMBOL(__local_irq_count); #endif /* rw semaphores */ @@ -183,6 +180,8 @@ EXPORT_SYMBOL_PRIVATE(flushw_user); +EXPORT_SYMBOL(__flush_dcache_page); + EXPORT_SYMBOL(mstk48t02_regs); EXPORT_SYMBOL(request_fast_irq); #if CONFIG_SBUS @@ -279,7 +278,6 @@ EXPORT_SYMBOL(strstr); #ifdef CONFIG_SOLARIS_EMUL_MODULE -EXPORT_SYMBOL(getname32); EXPORT_SYMBOL(linux_sparc_syscall); EXPORT_SYMBOL(rtrap); EXPORT_SYMBOL(show_regs); diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/kernel/sunos_ioctl32.c linux/arch/sparc64/kernel/sunos_ioctl32.c --- v2.4.0-test5/linux/arch/sparc64/kernel/sunos_ioctl32.c Sun Oct 4 10:22:43 1998 +++ linux/arch/sparc64/kernel/sunos_ioctl32.c Fri Aug 4 18:16:11 2000 @@ -1,4 +1,4 @@ -/* $Id: sunos_ioctl32.c,v 1.10 1998/08/15 20:42:46 davem Exp $ +/* $Id: sunos_ioctl32.c,v 1.11 2000/07/30 23:12:24 davem Exp $ * sunos_ioctl32.c: SunOS ioctl compatability on sparc64. * * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) @@ -98,7 +98,6 @@ { int ret = -EBADF; - lock_kernel(); if(fd >= SUNOS_NR_OPEN) goto out; if(!fcheck(fd)) @@ -281,6 +280,5 @@ /* so stupid... */ ret = (ret == -EINVAL ? -EOPNOTSUPP : ret); out: - unlock_kernel(); return ret; } diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/kernel/sys_sparc.c linux/arch/sparc64/kernel/sys_sparc.c --- v2.4.0-test5/linux/arch/sparc64/kernel/sys_sparc.c Fri Jul 14 12:12:08 2000 +++ linux/arch/sparc64/kernel/sys_sparc.c Fri Aug 4 18:16:11 2000 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc.c,v 1.44 2000/07/10 20:57:35 davem Exp $ +/* $Id: sys_sparc.c,v 1.45 2000/07/30 23:12:24 davem Exp $ * linux/arch/sparc64/kernel/sys_sparc.c * * This file contains various random system calls that @@ -299,13 +299,14 @@ static int count=0; /* Don't make the system unusable, if someone goes stuck */ - if (count++ > 5) return -ENOSYS; - lock_kernel(); + if (count++ > 5) + return -ENOSYS; + printk ("Unimplemented SPARC system call %ld\n",regs->u_regs[1]); #ifdef DEBUG_UNIMP_SYSCALL show_regs (regs); #endif - unlock_kernel(); + return -ENOSYS; } @@ -316,7 +317,6 @@ { siginfo_t info; - lock_kernel(); #ifdef DEBUG_SPARC_BREAKPOINT printk ("TRAP: Entering kernel PC=%lx, nPC=%lx\n", regs->tpc, regs->tnpc); #endif @@ -329,7 +329,6 @@ #ifdef DEBUG_SPARC_BREAKPOINT printk ("TRAP: Returning to space: PC=%lx nPC=%lx\n", regs->tpc, regs->tnpc); #endif - unlock_kernel(); } extern void check_pending(int signum); @@ -364,7 +363,7 @@ asmlinkage int solaris_syscall(struct pt_regs *regs) { static int count = 0; - lock_kernel(); + regs->tpc = regs->tnpc; regs->tnpc += 4; if(++count <= 5) { @@ -372,7 +371,7 @@ show_regs (regs); } send_sig(SIGSEGV, current, 1); - unlock_kernel(); + return -ENOSYS; } @@ -380,13 +379,13 @@ asmlinkage int sunos_syscall(struct pt_regs *regs) { static int count = 0; - lock_kernel(); + regs->tpc = regs->tnpc; regs->tnpc += 4; if(++count <= 20) printk ("SunOS binary emulation not compiled in\n"); force_sig(SIGSEGV, current); - unlock_kernel(); + return -ENOSYS; } #endif @@ -408,32 +407,37 @@ put_user_ret(NULL, old_d, -EFAULT); return 0; } - lock_kernel(); if (!current->thread.utraps) { - current->thread.utraps = kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), GFP_KERNEL); + current->thread.utraps = + kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), GFP_KERNEL); if (!current->thread.utraps) return -ENOMEM; current->thread.utraps[0] = 1; memset(current->thread.utraps+1, 0, UT_TRAP_INSTRUCTION_31*sizeof(long)); } else { - if ((utrap_handler_t)current->thread.utraps[type] != new_p && current->thread.utraps[0] > 1) { + if ((utrap_handler_t)current->thread.utraps[type] != new_p && + current->thread.utraps[0] > 1) { long *p = current->thread.utraps; - - current->thread.utraps = kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), GFP_KERNEL); + + current->thread.utraps = + kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), + GFP_KERNEL); if (!current->thread.utraps) { current->thread.utraps = p; return -ENOMEM; } p[0]--; current->thread.utraps[0] = 1; - memcpy(current->thread.utraps+1, p+1, UT_TRAP_INSTRUCTION_31*sizeof(long)); + memcpy(current->thread.utraps+1, p+1, + UT_TRAP_INSTRUCTION_31*sizeof(long)); } } if (old_p) - put_user_ret((utrap_handler_t)(current->thread.utraps[type]), old_p, -EFAULT); + put_user_ret((utrap_handler_t)(current->thread.utraps[type]), + old_p, -EFAULT); if (old_d) put_user_ret(NULL, old_d, -EFAULT); current->thread.utraps[type] = (long)new_p; - unlock_kernel(); + return 0; } diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c --- v2.4.0-test5/linux/arch/sparc64/kernel/sys_sparc32.c Thu Jul 27 17:38:00 2000 +++ linux/arch/sparc64/kernel/sys_sparc32.c Wed Aug 9 13:49:56 2000 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.156 2000/07/13 10:59:13 davem Exp $ +/* $Id: sys_sparc32.c,v 1.159 2000/08/08 02:47:50 davem Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -253,45 +253,6 @@ return high2lowgid(current->egid); } -/* In order to reduce some races, while at the same time doing additional - * checking and hopefully speeding things up, we copy filenames to the - * kernel data space before using them.. - * - * POSIX.1 2.4: an empty pathname is invalid (ENOENT). - */ -static inline int do_getname32(const char *filename, char *page) -{ - int retval; - - /* 32bit pointer will be always far below TASK_SIZE :)) */ - retval = strncpy_from_user((char *)page, (char *)filename, PAGE_SIZE); - if (retval > 0) { - if (retval < PAGE_SIZE) - return 0; - return -ENAMETOOLONG; - } else if (!retval) - retval = -ENOENT; - return retval; -} - -char * getname32(const char *filename) -{ - char *tmp, *result; - - result = ERR_PTR(-ENOMEM); - tmp = __getname(); - if (tmp) { - int retval = do_getname32(filename, tmp); - - result = tmp; - if (retval < 0) { - putname(tmp); - result = ERR_PTR(retval); - } - } - return result; -} - /* 32-bit timeval and related flotsam. */ struct timeval32 @@ -799,7 +760,6 @@ { int version, err; - lock_kernel(); version = call >> 16; /* hack for backward compatibility */ call &= 0xffff; @@ -861,7 +821,6 @@ err = -EINVAL; out: - unlock_kernel(); return err; } @@ -953,7 +912,7 @@ return sys_quotactl(cmd, special, id, (caddr_t)addr); } - spec = getname32 (special); + spec = getname (special); err = PTR_ERR(spec); if (IS_ERR(spec)) return err; old_fs = get_fs (); @@ -998,7 +957,7 @@ mm_segment_t old_fs = get_fs(); char *pth; - pth = getname32 (path); + pth = getname (path); ret = PTR_ERR(pth); if (!IS_ERR(pth)) { set_fs (KERNEL_DS); @@ -1064,7 +1023,7 @@ if (get_user (t.actime, ×->actime) || __get_user (t.modtime, ×->modtime)) return -EFAULT; - filenam = getname32 (filename); + filenam = getname (filename); ret = PTR_ERR(filenam); if (!IS_ERR(filenam)) { old_fs = get_fs(); @@ -1078,7 +1037,8 @@ struct iovec32 { u32 iov_base; __kernel_size_t32 iov_len; }; -typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *); +typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *); +typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *); static long do_readv_writev32(int type, struct file *file, const struct iovec32 *vector, u32 count) @@ -1088,14 +1048,15 @@ struct iovec *iov=iovstack, *ivp; struct inode *inode; long retval, i; - IO_fn_t fn; + io_fn_t fn; + iov_fn_t fnv; /* First get the "struct iovec" from user memory and * verify all the pointers */ if (!count) return 0; - if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count)) + if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count)) return -EFAULT; if (count > UIO_MAXIOV) return -EINVAL; @@ -1127,33 +1088,19 @@ retval = locks_verify_area((type == VERIFY_WRITE ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE), inode, file, file->f_pos, tot_len); - if (retval) { - if (iov != iovstack) - kfree(iov); - return retval; - } + if (retval) + goto out; - /* Then do the actual IO. Note that sockets need to be handled - * specially as they have atomicity guarantees and can handle - * iovec's natively - */ - if (inode->i_sock) { - int err; - err = sock_readv_writev(type, inode, file, iov, count, tot_len); - if (iov != iovstack) - kfree(iov); - return err; + /* VERIFY_WRITE actually means a read, as we write to user space */ + fnv = (type == VERIFY_WRITE ? file->f_op->readv : file->f_op->writev); + if (fnv) { + retval = fnv(file, iov, count, &file->f_pos); + goto out; } - if (!file->f_op) { - if (iov != iovstack) - kfree(iov); - return -EINVAL; - } - /* VERIFY_WRITE actually means a read, as we write to user space */ - fn = file->f_op->read; - if (type == VERIFY_READ) - fn = (IO_fn_t) file->f_op->write; + fn = (type == VERIFY_WRITE ? file->f_op->read : + (io_fn_t) file->f_op->write); + ivp = iov; while (count > 0) { void * base; @@ -1165,17 +1112,18 @@ count--; nr = fn(file, base, len, &file->f_pos); if (nr < 0) { - if (retval) - break; - retval = nr; + if (!retval) + retval = nr; break; } retval += nr; if (nr != len) break; } +out: if (iov != iovstack) kfree(iov); + return retval; } @@ -1188,7 +1136,8 @@ if(!file) goto bad_file; - if (file->f_op && file->f_op->read && (file->f_mode & FMODE_READ)) + if (file->f_op && (file->f_mode & FMODE_READ) && + (file->f_op->readv || file->f_op->read)) ret = do_readv_writev32(VERIFY_WRITE, file, vector, count); fput(file); @@ -1204,7 +1153,8 @@ file = fget(fd); if(!file) goto bad_file; - if (file->f_op && file->f_op->write && (file->f_mode & FMODE_WRITE)) + if (file->f_op && (file->f_mode & FMODE_WRITE) && + (file->f_op->writev || file->f_op->write)) ret = do_readv_writev32(VERIFY_READ, file, vector, count); fput(file); @@ -1572,6 +1522,16 @@ return err; } +/* Perhaps this belongs in fs.h or similar. -DaveM */ +static __inline__ int +do_revalidate(struct dentry *dentry) +{ + struct inode * inode = dentry->d_inode; + if (inode->i_op && inode->i_op->revalidate) + return inode->i_op->revalidate(dentry); + return 0; +} + asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf) { struct nameidata nd; @@ -1579,16 +1539,9 @@ error = user_path_walk(filename, &nd); if (!error) { - struct inode *inode = nd.dentry->d_inode; - - if (inode->i_op && - inode->i_op->revalidate) - error = inode->i_op->revalidate(nd.dentry); - else - error = 0; + error = do_revalidate(nd.dentry); if (!error) - error = cp_new_stat32(inode, statbuf); - + error = cp_new_stat32(nd.dentry->d_inode, statbuf); path_release(&nd); } return error; @@ -1601,15 +1554,9 @@ error = user_path_walk_link(filename, &nd); if (!error) { - struct inode *inode = nd.dentry->d_inode; - - if (inode->i_op && - inode->i_op->revalidate) - error = inode->i_op->revalidate(nd.dentry); - else - error = 0; + error = do_revalidate(nd.dentry); if (!error) - error = cp_new_stat32(inode, statbuf); + error = cp_new_stat32(nd.dentry->d_inode, statbuf); path_release(&nd); } @@ -1623,16 +1570,11 @@ f = fget(fd); if (f) { - struct inode *inode = f->f_dentry->d_inode; + struct dentry * dentry = f->f_dentry; - if (inode->i_op && - inode->i_op->revalidate) - err = inode->i_op->revalidate(f->f_dentry); - else - err = 0; + err = do_revalidate(dentry); if (!err) - err = cp_new_stat32(inode, statbuf); - + err = cp_new_stat32(dentry->d_inode, statbuf); fput(f); } return err; @@ -1738,7 +1680,6 @@ is_smb = is_ncp = 0; - lock_kernel(); err = copy_mount_stuff_to_kernel((const void *)type, &type_page); if (err) goto out; @@ -1764,16 +1705,20 @@ goto dev_out; if (!is_smb && !is_ncp) { + lock_kernel(); err = do_mount((char*)dev_page, (char*)dir_page, (char*)type_page, new_flags, (char*)data_page); + unlock_kernel(); } else { if (is_ncp) do_ncp_super_data_conv((void *)data_page); else do_smb_super_data_conv((void *)data_page); + lock_kernel(); err = do_mount((char*)dev_page, (char*)dir_page, (char*)type_page, new_flags, (char*)data_page); + unlock_kernel(); } free_page(dir_page); @@ -1787,7 +1732,6 @@ free_page(type_page); out: - unlock_kernel(); return err; } @@ -2234,34 +2178,9 @@ 24 for IPv6, about 80 for AX.25 */ -/* XXX These as well... */ -extern __inline__ struct socket *socki_lookup(struct inode *inode) -{ - return &inode->u.socket_i; -} - -extern __inline__ struct socket *sockfd_lookup(int fd, int *err) -{ - struct file *file; - struct inode *inode; - - if (!(file = fget(fd))) - { - *err = -EBADF; - return NULL; - } - - inode = file->f_dentry->d_inode; - if (!inode || !inode->i_sock || !socki_lookup(inode)) - { - *err = -ENOTSOCK; - fput(file); - return NULL; - } - - return socki_lookup(inode); -} +extern struct socket *sockfd_lookup(int fd, int *err); +/* XXX This as well... */ extern __inline__ void sockfd_put(struct socket *sock) { fput(sock->file); @@ -2678,7 +2597,6 @@ } kern_msg.msg_flags = user_flags; - lock_kernel(); sock = sockfd_lookup(fd, &err); if (sock != NULL) { if (sock->file->f_flags & O_NONBLOCK) @@ -2686,7 +2604,6 @@ err = sock_sendmsg(sock, &kern_msg, total_len); sockfd_put(sock); } - unlock_kernel(); /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */ if(ctl_buf != ctl) @@ -2725,7 +2642,6 @@ cmsg_ptr = (unsigned long) kern_msg.msg_control; kern_msg.msg_flags = 0; - lock_kernel(); sock = sockfd_lookup(fd, &err); if (sock != NULL) { struct scm_cookie scm; @@ -2762,7 +2678,6 @@ } sockfd_put(sock); } - unlock_kernel(); if(uaddr != NULL && err >= 0) err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); @@ -3084,7 +2999,7 @@ if((u32)regs->u_regs[UREG_G1] == 0) base = 1; - filename = getname32((char *)AA(regs->u_regs[base + UREG_I0])); + filename = getname((char *)AA(regs->u_regs[base + UREG_I0])); error = PTR_ERR(filename); if(IS_ERR(filename)) goto out; @@ -3926,7 +3841,7 @@ mm_segment_t old_fs; int ret; - kfilename = getname32(filename); + kfilename = getname(filename); ret = PTR_ERR(kfilename); if (!IS_ERR(kfilename)) { if (tvs) { diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c --- v2.4.0-test5/linux/arch/sparc64/kernel/sys_sunos32.c Fri Jul 14 12:12:08 2000 +++ linux/arch/sparc64/kernel/sys_sunos32.c Fri Aug 4 18:16:11 2000 @@ -1,4 +1,4 @@ -/* $Id: sys_sunos32.c,v 1.52 2000/07/10 20:57:35 davem Exp $ +/* $Id: sys_sunos32.c,v 1.53 2000/07/30 23:12:24 davem Exp $ * sys_sunos32.c: SunOS binary compatability layer on sparc64. * * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu) @@ -179,21 +179,18 @@ int error, oldbrk; /* This should do it hopefully... */ - lock_kernel(); oldbrk = (int)current->mm->brk; error = sunos_brk(((int) current->mm->brk) + increment); if(!error) error = oldbrk; - unlock_kernel(); return error; } asmlinkage u32 sunos_sstk(int increment) { - lock_kernel(); printk("%s: Call to sunos_sstk(increment<%d>) is unsupported\n", current->comm, increment); - unlock_kernel(); + return (u32)-1; } @@ -213,12 +210,13 @@ asmlinkage void sunos_vadvise(u32 strategy) { + static int count = 0; + /* I wanna see who uses this... */ - lock_kernel(); - printk("%s: Advises us to use %s paging strategy\n", - current->comm, - strategy <= 3 ? vstrings[strategy] : "BOGUS"); - unlock_kernel(); + if (count++ < 5) + printk("%s: Advises us to use %s paging strategy\n", + current->comm, + strategy <= 3 ? vstrings[strategy] : "BOGUS"); } /* This just wants the soft limit (ie. rlim_cur element) of the RLIMIT_NOFILE @@ -457,7 +455,6 @@ siginfo_t info; static int cnt; - lock_kernel(); regs = current->thread.kregs; info.si_signo = SIGSYS; info.si_errno = 0; @@ -470,7 +467,6 @@ (int) regs->u_regs[UREG_G1]); show_regs(regs); } - unlock_kernel(); return -ENOSYS; } @@ -726,7 +722,7 @@ if (!capable (CAP_SYS_ADMIN)) return -EPERM; - lock_kernel(); + /* We don't handle the integer fs type */ if ((flags & SMNT_NEWTYPE) == 0) goto out; @@ -772,7 +768,9 @@ ret = PTR_ERR(dev_fname); if (IS_ERR(dev_fname)) goto out2; + lock_kernel(); ret = do_mount(dev_fname, dir_page, type_page, linux_flags, NULL); + unlock_kernel(); if (dev_fname) putname(dev_fname); out2: @@ -780,7 +778,6 @@ out1: putname(dir_page); out: - unlock_kernel(); return ret; } @@ -818,12 +815,7 @@ extern int kill_pg(int, int, int); asmlinkage int sunos_killpg(int pgrp, int sig) { - int ret; - - lock_kernel(); - ret = kill_pg(pgrp, sig, 0); - unlock_kernel(); - return ret; + return kill_pg(pgrp, sig, 0); } asmlinkage int sunos_audit(void) @@ -836,9 +828,8 @@ { u32 ret; - lock_kernel(); ret = (((u32)idprom->id_machtype << 24) | ((u32)idprom->id_sernum)); - unlock_kernel(); + return ret; } diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/kernel/traps.c linux/arch/sparc64/kernel/traps.c --- v2.4.0-test5/linux/arch/sparc64/kernel/traps.c Tue May 23 15:31:34 2000 +++ linux/arch/sparc64/kernel/traps.c Fri Aug 4 18:16:11 2000 @@ -1,4 +1,4 @@ -/* $Id: traps.c,v 1.66 2000/05/09 17:40:14 davem Exp $ +/* $Id: traps.c,v 1.67 2000/07/30 23:12:24 davem Exp $ * arch/sparc64/kernel/traps.c * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -255,7 +255,6 @@ { siginfo_t info; - lock_kernel (); if (lvl < 0x100) { char buffer[24]; @@ -270,17 +269,14 @@ info.si_addr = (void *)regs->tpc; info.si_trapno = lvl - 0x100; force_sig_info(SIGILL, &info, current); - unlock_kernel (); } void bad_trap_tl1 (struct pt_regs *regs, long lvl) { char buffer[24]; - lock_kernel(); sprintf (buffer, "Bad trap %lx at tl>0", lvl); die_if_kernel (buffer, regs); - unlock_kernel(); } void instruction_access_exception (struct pt_regs *regs, @@ -288,7 +284,6 @@ { siginfo_t info; - lock_kernel(); if (regs->tstate & TSTATE_PRIV) { #if 1 printk("instruction_access_exception: Shit SFSR[%016lx] SFAR[%016lx], going.\n", @@ -302,7 +297,6 @@ info.si_addr = (void *)regs->tpc; info.si_trapno = 0; force_sig_info(SIGSEGV, &info, current); - unlock_kernel(); } void data_access_exception (struct pt_regs *regs, @@ -343,9 +337,7 @@ info.si_code = SEGV_MAPERR; info.si_addr = (void *)sfar; info.si_trapno = 0; - lock_kernel(); force_sig_info(SIGSEGV, &info, current); - unlock_kernel(); } #ifdef CONFIG_PCI @@ -389,9 +381,7 @@ info.si_code = BUS_OBJERR; info.si_addr = (void *)0; info.si_trapno = 0; - lock_kernel(); force_sig_info(SIGBUS, &info, current); - unlock_kernel(); } void do_dae(struct pt_regs *regs) @@ -692,7 +682,6 @@ smp_report_regs(); #endif - lock_kernel(); /* Or else! */ if(regs->tstate & TSTATE_PRIV) do_exit(SIGKILL); do_exit(SIGSEGV); diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/mm/fault.c linux/arch/sparc64/mm/fault.c --- v2.4.0-test5/linux/arch/sparc64/mm/fault.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc64/mm/fault.c Wed Aug 9 13:49:56 2000 @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.48 2000/05/03 06:37:03 davem Exp $ +/* $Id: fault.c,v 1.49 2000/08/09 00:00:15 davem Exp $ * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -110,7 +110,7 @@ if(!pte_present(pte)) goto out; - pa = phys_base + (pte_pagenr(pte) << PAGE_SHIFT); + pa = phys_base + (sparc64_pte_pagenr(pte) << PAGE_SHIFT); pa += (tpc & ~PAGE_MASK); /* Use phys bypass so we don't pollute dtlb/dcache. */ diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/mm/generic.c linux/arch/sparc64/mm/generic.c --- v2.4.0-test5/linux/arch/sparc64/mm/generic.c Wed Dec 29 13:13:14 1999 +++ linux/arch/sparc64/mm/generic.c Wed Aug 9 13:49:56 2000 @@ -1,4 +1,4 @@ -/* $Id: generic.c,v 1.13 1999/12/20 05:02:33 davem Exp $ +/* $Id: generic.c,v 1.14 2000/08/09 00:00:15 davem Exp $ * generic.c: Generic Sparc mm routines that are not dependent upon * MMU type but are Sparc specific. * @@ -18,14 +18,14 @@ if (pte_none(page)) return; if (pte_present(page)) { - unsigned long nr = pte_pagenr(page); - if (nr >= max_mapnr || PageReserved(mem_map+nr)) + struct page *ptpage = pte_page(page); + if ((!VALID_PAGE(ptpage)) || PageReserved(ptpage)) return; /* * free_page() used to be able to clear swap cache * entries. We may now have to do it manually. */ - free_page_and_swap_cache(mem_map+nr); + free_page_and_swap_cache(ptpage); return; } swap_free(pte_to_swp_entry(page)); diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c --- v2.4.0-test5/linux/arch/sparc64/mm/init.c Tue May 23 15:31:34 2000 +++ linux/arch/sparc64/mm/init.c Wed Aug 9 13:49:56 2000 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.152 2000/05/09 17:40:14 davem Exp $ +/* $Id: init.c,v 1.154 2000/08/09 00:00:15 davem Exp $ * arch/sparc64/mm/init.c * * Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu) @@ -746,7 +746,7 @@ pte_t *pte; set_page_count((page + 1), 1); - paddr = page_address(page); + paddr = (unsigned long) page_address(page); memset((char *)paddr, 0, (PAGE_SIZE << 1)); if (!color) { @@ -1242,7 +1242,7 @@ page = (addr + ((unsigned long) __va(phys_base)) - ((unsigned long) &empty_zero_page)); - p = mem_map + MAP_NR(page); + p = virt_to_page(page); ClearPageReserved(p); set_page_count(p, 1); @@ -1257,7 +1257,7 @@ if (start < end) printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { - struct page *p = mem_map + MAP_NR(start); + struct page *p = virt_to_page(start); ClearPageReserved(p); set_page_count(p, 1); diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/mm/ultra.S linux/arch/sparc64/mm/ultra.S --- v2.4.0-test5/linux/arch/sparc64/mm/ultra.S Fri Jul 14 12:12:08 2000 +++ linux/arch/sparc64/mm/ultra.S Sun Aug 6 11:43:17 2000 @@ -1,4 +1,4 @@ -/* $Id: ultra.S,v 1.44 2000/07/10 20:57:35 davem Exp $ +/* $Id: ultra.S,v 1.46 2000/08/05 13:30:33 davem Exp $ * ultra.S: Don't expand these all over the place... * * Copyright (C) 1997, 2000 David S. Miller (davem@redhat.com) @@ -205,6 +205,30 @@ stxa %g0, [%o1 + %o2] ASI_IC_TAG flush %g6 ba,a,pt %xcc, 3b + + .align 64 + .globl __flush_dcache_page +__flush_dcache_page: + sub %o0, %g4, %o0 + clr %o1 + srlx %o0, 11, %o0 + sethi %hi(1 << 14), %o2 +1: ldxa [%o1] ASI_DCACHE_TAG, %o3 + andn %o3, 0x3, %o3 + cmp %o0, %o3 + bne,pt %xcc, 2f + nop + stxa %g0, [%o1] ASI_DCACHE_TAG + membar #Sync +2: add %o1, (1 << 5), %o1 + cmp %o1, %o2 + bne,pt %xcc, 1b + nop + /* The I-cache does not snoop local stores so we + * better flush that too. + */ + ba,pt %xcc, __flush_icache_page + sllx %o0, 11, %o0 .align 32 __prefill_dtlb: diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/solaris/fs.c linux/arch/sparc64/solaris/fs.c --- v2.4.0-test5/linux/arch/sparc64/solaris/fs.c Fri Jul 14 12:12:08 2000 +++ linux/arch/sparc64/solaris/fs.c Fri Aug 4 18:16:11 2000 @@ -1,4 +1,4 @@ -/* $Id: fs.c,v 1.21 2000/07/10 20:57:35 davem Exp $ +/* $Id: fs.c,v 1.22 2000/07/28 12:15:02 davem Exp $ * fs.c: fs related syscall emulation for Solaris * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -25,8 +25,6 @@ #include "conv.h" -extern char * getname32(u32 filename); - #define R4_DEV(DEV) ((DEV & 0xff) | ((DEV & 0xff00) << 10)) #define R4_MAJOR(DEV) (((DEV) >> 18) & 0x3fff) #define R4_MINOR(DEV) ((DEV) & 0x3ffff) @@ -136,7 +134,7 @@ int (*sys_newstat)(char *,struct stat *) = (int (*)(char *,struct stat *))SYS(stat); - filenam = getname32 (filename); + filenam = getname ((char *)A(filename)); ret = PTR_ERR(filenam); if (!IS_ERR(filenam)) { set_fs (KERNEL_DS); @@ -164,7 +162,7 @@ int (*sys_newstat)(char *,struct stat *) = (int (*)(char *,struct stat *))SYS(stat); - filenam = getname32 (filename); + filenam = getname ((char *)A(filename)); ret = PTR_ERR(filenam); if (!IS_ERR(filenam)) { set_fs (KERNEL_DS); @@ -186,7 +184,7 @@ int (*sys_newlstat)(char *,struct stat *) = (int (*)(char *,struct stat *))SYS(lstat); - filenam = getname32 (filename); + filenam = getname ((char *)A(filename)); ret = PTR_ERR(filenam); if (!IS_ERR(filenam)) { set_fs (KERNEL_DS); @@ -213,7 +211,7 @@ int (*sys_newlstat)(char *,struct stat *) = (int (*)(char *,struct stat *))SYS(lstat); - filenam = getname32 (filename); + filenam = getname ((char *)A(filename)); ret = PTR_ERR(filenam); if (!IS_ERR(filenam)) { set_fs (KERNEL_DS); diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/solaris/ioctl.c linux/arch/sparc64/solaris/ioctl.c --- v2.4.0-test5/linux/arch/sparc64/solaris/ioctl.c Wed Dec 29 13:13:15 1999 +++ linux/arch/sparc64/solaris/ioctl.c Fri Aug 4 18:16:11 2000 @@ -1,4 +1,4 @@ -/* $Id: ioctl.c,v 1.14 1999/09/22 09:28:50 davem Exp $ +/* $Id: ioctl.c,v 1.15 2000/07/28 12:15:02 davem Exp $ * ioctl.c: Solaris ioctl emulation. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -31,9 +31,6 @@ #include "conv.h" #include "socksys.h" -extern char *getname32(u32 filename); -#define putname32 putname - extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); extern asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, @@ -486,7 +483,7 @@ return -ENOSYS; case 2: /* I_PUSH */ { - p = getname32 (arg); + p = getname ((char *)A(arg)); if (IS_ERR (p)) return PTR_ERR(p); ret = -EINVAL; @@ -503,7 +500,7 @@ break; } } - putname32 (p); + putname (p); return ret; } case 3: /* I_POP */ @@ -546,7 +543,7 @@ case 11: /* I_FIND */ { int i; - p = getname32 (arg); + p = getname ((char *)A(arg)); if (IS_ERR (p)) return PTR_ERR(p); ret = 0; @@ -557,7 +554,7 @@ break; } } - putname32 (p); + putname (p); return ret; } case 19: /* I_SWROPT */ diff -u --recursive --new-file v2.4.0-test5/linux/arch/sparc64/solaris/timod.c linux/arch/sparc64/solaris/timod.c --- v2.4.0-test5/linux/arch/sparc64/solaris/timod.c Fri Jul 14 12:12:08 2000 +++ linux/arch/sparc64/solaris/timod.c Fri Aug 4 18:16:11 2000 @@ -1,4 +1,4 @@ -/* $Id: timod.c,v 1.9 2000/07/12 23:21:02 davem Exp $ +/* $Id: timod.c,v 1.10 2000/07/28 12:15:02 davem Exp $ * timod.c: timod emulation. * * Copyright (C) 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz) @@ -26,9 +26,6 @@ #include "conv.h" #include "socksys.h" - -extern char *getname32(u32 filename); -#define putname32 putname extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/Makefile linux/drivers/Makefile --- v2.4.0-test5/linux/drivers/Makefile Mon Jul 10 16:47:21 2000 +++ linux/drivers/Makefile Sun Aug 6 11:23:40 2000 @@ -171,6 +171,8 @@ # When MOD_LIST_NAME is set, make will try to add $(MOD_SUB_DIRS).o to # modules/MOD_LIST_NAME. We don't have hamradio.o and Linus # sort of insisted on making hamradio/ a subdirectory of drivers/net/. +# #FIXME# MOD_LIST_NAME doesn't exist any more -- does this comment +# #FIXME# still mean anything? ifeq ($(CONFIG_HAMRADIO),y) SUB_DIRS += net/hamradio diff -u --recursive --new-file v2.4.0-test5/linux/drivers/acorn/block/Makefile linux/drivers/acorn/block/Makefile --- v2.4.0-test5/linux/drivers/acorn/block/Makefile Mon Mar 27 08:08:22 2000 +++ linux/drivers/acorn/block/Makefile Sun Aug 6 11:23:40 2000 @@ -10,7 +10,6 @@ # L_TARGET := acorn-block.a -MOD_LIST_NAME := ACORN_BLOCK_MODULES obj-y := obj-m := diff -u --recursive --new-file v2.4.0-test5/linux/drivers/acorn/char/keyb_arc.c linux/drivers/acorn/char/keyb_arc.c --- v2.4.0-test5/linux/drivers/acorn/char/keyb_arc.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/acorn/char/keyb_arc.c Wed Aug 9 14:11:11 2000 @@ -33,6 +33,7 @@ #include "../../char/busmouse.h" +extern struct tasklet_struct keyboard_tasklet; extern void kbd_reset_kdown(void); #define VERSION 108 @@ -402,7 +403,7 @@ { kbd_pt_regs = regs; if (handle_rawcode(inb(IOC_KARTRX))) - mark_bh (KEYBOARD_BH); + tasklet_schedule(&keyboard_tasklet); } static void a5kkbd_tx(int irq, void *dev_id, struct pt_regs *regs) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/acorn/char/keyb_ps2.c linux/drivers/acorn/char/keyb_ps2.c --- v2.4.0-test5/linux/drivers/acorn/char/keyb_ps2.c Tue Apr 11 15:09:15 2000 +++ linux/drivers/acorn/char/keyb_ps2.c Wed Aug 9 14:11:11 2000 @@ -341,6 +341,5 @@ (void)IOMD_KARTRX; restore_flags (flags); - printk (KERN_INFO "PS/2 keyboard driver v%d.%02d\n", VERSION/100, VERSION%100); return 0; } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/acorn/net/Makefile linux/drivers/acorn/net/Makefile --- v2.4.0-test5/linux/drivers/acorn/net/Makefile Tue May 23 15:31:34 2000 +++ linux/drivers/acorn/net/Makefile Sun Aug 6 11:23:40 2000 @@ -4,7 +4,6 @@ # O_TARGET := acorn-net.o -MOD_LIST_NAME := ACORN_NET_MODULES obj-y := obj-m := diff -u --recursive --new-file v2.4.0-test5/linux/drivers/acorn/scsi/Makefile linux/drivers/acorn/scsi/Makefile --- v2.4.0-test5/linux/drivers/acorn/scsi/Makefile Mon Mar 27 08:08:22 2000 +++ linux/drivers/acorn/scsi/Makefile Sun Aug 6 11:23:40 2000 @@ -3,7 +3,6 @@ # L_TARGET := acorn-scsi.a -MOD_LIST_NAME := ACORN_SCSI_MODULES obj-y := obj-m := diff -u --recursive --new-file v2.4.0-test5/linux/drivers/acorn/scsi/fas216.c linux/drivers/acorn/scsi/fas216.c --- v2.4.0-test5/linux/drivers/acorn/scsi/fas216.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/acorn/scsi/fas216.c Wed Aug 9 14:11:11 2000 @@ -2463,7 +2463,7 @@ * IRQs after the sleep. */ spin_unlock_irq(&io_request_lock); - scsi_sleep(5); + scsi_sleep(25*HZ/100); spin_lock_irq(&io_request_lock); /* @@ -2628,7 +2628,7 @@ * scsi standard says wait 250ms */ spin_unlock_irq(&io_request_lock); - scsi_sleep(5); + scsi_sleep(25*HZ/100); spin_lock_irq(&io_request_lock); outb(info->scsi.cfg[0], REG_CNTL1(info)); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/atm/Makefile linux/drivers/atm/Makefile --- v2.4.0-test5/linux/drivers/atm/Makefile Fri Jun 23 21:55:08 2000 +++ linux/drivers/atm/Makefile Sun Aug 6 11:23:40 2000 @@ -6,7 +6,6 @@ O_TARGET := atm.o O_OBJS := atmdev_init.o M_OBJS := -MOD_LIST_NAME := ATM_MODULES include ../../.config diff -u --recursive --new-file v2.4.0-test5/linux/drivers/atm/iphase.c linux/drivers/atm/iphase.c --- v2.4.0-test5/linux/drivers/atm/iphase.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/atm/iphase.c Sun Aug 6 22:20:09 2000 @@ -1712,12 +1712,15 @@ vcc = ATM_SKB(skb)->vcc; if (!vcc) { printk("tx_dle_intr: vcc is null\n"); + spin_unlock_irqrestore(&iadev->tx_lock, flags); dev_kfree_skb_any(skb); + return; } iavcc = INPH_IA_VCC(vcc); if (!iavcc) { printk("tx_dle_intr: iavcc is null\n"); + spin_unlock_irqrestore(&iadev->tx_lock, flags); dev_kfree_skb_any(skb); return; } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/block/DAC960.c linux/drivers/block/DAC960.c --- v2.4.0-test5/linux/drivers/block/DAC960.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/block/DAC960.c Fri Aug 4 13:11:00 2000 @@ -1,8 +1,8 @@ /* - Linux Driver for Mylex DAC960 and DAC1100 PCI RAID Controllers + Linux Driver for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers - Copyright 1998-1999 by Leonard N. Zubkoff + Copyright 1998-2000 by Leonard N. Zubkoff This program is free software; you may redistribute and/or modify it under the terms of the GNU General Public License Version 2 as published by the @@ -19,9 +19,8 @@ */ -#define DAC960_DriverVersion "2.3.5" -#define DAC960_DriverDate "23 January 2000" - +#define DAC960_DriverVersion "2.4.7" +#define DAC960_DriverDate "1 August 2000" #include @@ -38,11 +37,11 @@ #include #include #include +#include #include #include #include #include -#include #include #include "DAC960.h" @@ -56,7 +55,7 @@ /* - DAC960_ActiveControllerCount is the number of Active DAC960 Controllers + DAC960_ActiveControllerCount is the number of active DAC960 Controllers detected. */ @@ -74,23 +73,23 @@ /* - DAC960_FileOperations is the File Operations structure for DAC960 Logical - Disk Devices. - Leonard, no offence, but _where_ did this C dialect come from? + DAC960_BlockDeviceOperations is the Block Device Operations structure for + DAC960 Logical Disk Devices. */ -static struct block_device_operations DAC960_FileOperations = { - open: DAC960_Open, - release: DAC960_Release, - ioctl: DAC960_IOCTL, -}; +static BlockDeviceOperations_T + DAC960_BlockDeviceOperations = + { open: DAC960_Open, + release: DAC960_Release, + ioctl: DAC960_IOCTL }; + /* - DAC960_ProcDirectoryEntry is the DAC960 /proc/driver/rd directory entry. + DAC960_ProcDirectoryEntry is the DAC960 /proc/rd directory entry. */ -static PROC_DirectoryEntry_T * - DAC960_ProcDirectoryEntry = NULL; +static PROC_DirectoryEntry_T + *DAC960_ProcDirectoryEntry; /* @@ -121,7 +120,7 @@ */ static boolean DAC960_Failure(DAC960_Controller_T *Controller, - char *ErrorMessage) + unsigned char *ErrorMessage) { DAC960_Error("While configuring DAC960 PCI RAID Controller at\n", Controller); @@ -141,17 +140,128 @@ /* - DAC960_ClearCommand clears critical fields of Command. + DAC960_CreateAuxiliaryStructures allocates and initializes the auxiliary + data structures for Controller. It returns true on success and false on + failure. +*/ + +static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller) +{ + int CommandAllocationLength, CommandAllocationGroupSize; + int CommandsRemaining = 0, CommandIdentifier, CommandGroupByteCount; + void *AllocationPointer = NULL; + if (Controller->FirmwareType == DAC960_V1_Controller) + { + CommandAllocationLength = offsetof(DAC960_Command_T, V1.EndMarker); + CommandAllocationGroupSize = DAC960_V1_CommandAllocationGroupSize; + } + else + { + CommandAllocationLength = offsetof(DAC960_Command_T, V2.EndMarker); + CommandAllocationGroupSize = DAC960_V2_CommandAllocationGroupSize; + } + Controller->CommandAllocationGroupSize = CommandAllocationGroupSize; + Controller->FreeCommands = NULL; + for (CommandIdentifier = 1; + CommandIdentifier <= Controller->DriverQueueDepth; + CommandIdentifier++) + { + DAC960_Command_T *Command; + if (--CommandsRemaining <= 0) + { + CommandsRemaining = + Controller->DriverQueueDepth - CommandIdentifier + 1; + if (CommandsRemaining > CommandAllocationGroupSize) + CommandsRemaining = CommandAllocationGroupSize; + CommandGroupByteCount = + CommandsRemaining * CommandAllocationLength; + AllocationPointer = kmalloc(CommandGroupByteCount, GFP_ATOMIC); + if (AllocationPointer == NULL) + return DAC960_Failure(Controller, "AUXILIARY STRUCTURE CREATION"); + memset(AllocationPointer, 0, CommandGroupByteCount); + } + Command = (DAC960_Command_T *) AllocationPointer; + AllocationPointer += CommandAllocationLength; + Command->CommandIdentifier = CommandIdentifier; + Command->Controller = Controller; + Command->Next = Controller->FreeCommands; + Controller->FreeCommands = Command; + Controller->Commands[CommandIdentifier-1] = Command; + } + return true; +} + + +/* + DAC960_DestroyAuxiliaryStructures deallocates the auxiliary data + structures for Controller. +*/ + +static void DAC960_DestroyAuxiliaryStructures(DAC960_Controller_T *Controller) +{ + int i; + Controller->FreeCommands = NULL; + for (i = 0; i < Controller->DriverQueueDepth; i++) + { + DAC960_Command_T *Command = Controller->Commands[i]; + if (Command != NULL && + (Command->CommandIdentifier + % Controller->CommandAllocationGroupSize) == 1) + kfree(Command); + Controller->Commands[i] = NULL; + } + if (Controller->CombinedStatusBuffer != NULL) + { + kfree(Controller->CombinedStatusBuffer); + Controller->CombinedStatusBuffer = NULL; + Controller->CurrentStatusBuffer = NULL; + } + if (Controller->FirmwareType == DAC960_V1_Controller) return; + for (i = 0; i < DAC960_MaxLogicalDrives; i++) + if (Controller->V2.LogicalDeviceInformation[i] != NULL) + { + kfree(Controller->V2.LogicalDeviceInformation[i]); + Controller->V2.LogicalDeviceInformation[i] = NULL; + } + for (i = 0; i < DAC960_V2_MaxPhysicalDevices; i++) + { + if (Controller->V2.PhysicalDeviceInformation[i] != NULL) + { + kfree(Controller->V2.PhysicalDeviceInformation[i]); + Controller->V2.PhysicalDeviceInformation[i] = NULL; + } + if (Controller->V2.InquiryUnitSerialNumber[i] != NULL) + { + kfree(Controller->V2.InquiryUnitSerialNumber[i]); + Controller->V2.InquiryUnitSerialNumber[i] = NULL; + } + } +} + + +/* + DAC960_V1_ClearCommand clears critical fields of Command for DAC960 V1 + Firmware Controllers. +*/ + +static inline void DAC960_V1_ClearCommand(DAC960_Command_T *Command) +{ + DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + memset(CommandMailbox, 0, sizeof(DAC960_V1_CommandMailbox_T)); + Command->V1.CommandStatus = 0; +} + + +/* + DAC960_V2_ClearCommand clears critical fields of Command for DAC960 V2 + Firmware Controllers. */ -static inline void DAC960_ClearCommand(DAC960_Command_T *Command) +static inline void DAC960_V2_ClearCommand(DAC960_Command_T *Command) { - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; - CommandMailbox->Words[0] = 0; - CommandMailbox->Words[1] = 0; - CommandMailbox->Words[2] = 0; - CommandMailbox->Words[3] = 0; - Command->CommandStatus = 0; + DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + memset(CommandMailbox, 0, sizeof(DAC960_V2_CommandMailbox_T)); + Command->V2.CommandStatus = 0; } @@ -202,66 +312,181 @@ /* - DAC960_QueueCommand queues Command. + DAC960_BA_QueueCommand queues Command for DAC960 BA Series Controllers. */ -static void DAC960_QueueCommand(DAC960_Command_T *Command) +static void DAC960_BA_QueueCommand(DAC960_Command_T *Command) { DAC960_Controller_T *Controller = Command->Controller; void *ControllerBaseAddress = Controller->BaseAddress; - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; - DAC960_CommandMailbox_T *NextCommandMailbox; - CommandMailbox->Common.CommandIdentifier = Command - Controller->Commands; - switch (Controller->ControllerType) - { - case DAC960_V5_Controller: - NextCommandMailbox = Controller->NextCommandMailbox; - DAC960_V5_WriteCommandMailbox(NextCommandMailbox, CommandMailbox); - if (Controller->PreviousCommandMailbox1->Words[0] == 0 || - Controller->PreviousCommandMailbox2->Words[0] == 0) - { - if (Controller->DualModeMemoryMailboxInterface) - DAC960_V5_MemoryMailboxNewCommand(ControllerBaseAddress); - else DAC960_V5_HardwareMailboxNewCommand(ControllerBaseAddress); - } - Controller->PreviousCommandMailbox2 = Controller->PreviousCommandMailbox1; - Controller->PreviousCommandMailbox1 = NextCommandMailbox; - if (++NextCommandMailbox > Controller->LastCommandMailbox) - NextCommandMailbox = Controller->FirstCommandMailbox; - Controller->NextCommandMailbox = NextCommandMailbox; - break; - case DAC960_V4_Controller: - NextCommandMailbox = Controller->NextCommandMailbox; - DAC960_V4_WriteCommandMailbox(NextCommandMailbox, CommandMailbox); - if (Controller->PreviousCommandMailbox1->Words[0] == 0 || - Controller->PreviousCommandMailbox2->Words[0] == 0) - { - if (Controller->DualModeMemoryMailboxInterface) - DAC960_V4_MemoryMailboxNewCommand(ControllerBaseAddress); - else DAC960_V4_HardwareMailboxNewCommand(ControllerBaseAddress); - } - Controller->PreviousCommandMailbox2 = Controller->PreviousCommandMailbox1; - Controller->PreviousCommandMailbox1 = NextCommandMailbox; - if (++NextCommandMailbox > Controller->LastCommandMailbox) - NextCommandMailbox = Controller->FirstCommandMailbox; - Controller->NextCommandMailbox = NextCommandMailbox; - break; - case DAC960_V3_Controller: - while (DAC960_V3_MailboxFullP(ControllerBaseAddress)) - udelay(1); - DAC960_V3_WriteCommandMailbox(ControllerBaseAddress, CommandMailbox); - DAC960_V3_NewCommand(ControllerBaseAddress); - break; - } + DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_CommandMailbox_T *NextCommandMailbox = + Controller->V2.NextCommandMailbox; + CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier; + DAC960_BA_WriteCommandMailbox(NextCommandMailbox, CommandMailbox); + if (Controller->V2.PreviousCommandMailbox1->Words[0] == 0 || + Controller->V2.PreviousCommandMailbox2->Words[0] == 0) + DAC960_BA_MemoryMailboxNewCommand(ControllerBaseAddress); + Controller->V2.PreviousCommandMailbox2 = + Controller->V2.PreviousCommandMailbox1; + Controller->V2.PreviousCommandMailbox1 = NextCommandMailbox; + if (++NextCommandMailbox > Controller->V2.LastCommandMailbox) + NextCommandMailbox = Controller->V2.FirstCommandMailbox; + Controller->V2.NextCommandMailbox = NextCommandMailbox; } /* - DAC960_ExecuteCommand executes Command and waits for completion. It - returns true on success and false on failure. + DAC960_LP_QueueCommand queues Command for DAC960 LP Series Controllers. +*/ + +static void DAC960_LP_QueueCommand(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_CommandMailbox_T *NextCommandMailbox = + Controller->V2.NextCommandMailbox; + CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier; + DAC960_LP_WriteCommandMailbox(NextCommandMailbox, CommandMailbox); + if (Controller->V2.PreviousCommandMailbox1->Words[0] == 0 || + Controller->V2.PreviousCommandMailbox2->Words[0] == 0) + DAC960_LP_MemoryMailboxNewCommand(ControllerBaseAddress); + Controller->V2.PreviousCommandMailbox2 = + Controller->V2.PreviousCommandMailbox1; + Controller->V2.PreviousCommandMailbox1 = NextCommandMailbox; + if (++NextCommandMailbox > Controller->V2.LastCommandMailbox) + NextCommandMailbox = Controller->V2.FirstCommandMailbox; + Controller->V2.NextCommandMailbox = NextCommandMailbox; +} + + +/* + DAC960_LA_QueueCommandDualMode queues Command for DAC960 LA Series + Controllers with Dual Mode Firmware. +*/ + +static void DAC960_LA_QueueCommandDualMode(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + DAC960_V1_CommandMailbox_T *NextCommandMailbox = + Controller->V1.NextCommandMailbox; + CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier; + DAC960_LA_WriteCommandMailbox(NextCommandMailbox, CommandMailbox); + if (Controller->V1.PreviousCommandMailbox1->Words[0] == 0 || + Controller->V1.PreviousCommandMailbox2->Words[0] == 0) + DAC960_LA_MemoryMailboxNewCommand(ControllerBaseAddress); + Controller->V1.PreviousCommandMailbox2 = + Controller->V1.PreviousCommandMailbox1; + Controller->V1.PreviousCommandMailbox1 = NextCommandMailbox; + if (++NextCommandMailbox > Controller->V1.LastCommandMailbox) + NextCommandMailbox = Controller->V1.FirstCommandMailbox; + Controller->V1.NextCommandMailbox = NextCommandMailbox; +} + + +/* + DAC960_LA_QueueCommandSingleMode queues Command for DAC960 LA Series + Controllers with Single Mode Firmware. +*/ + +static void DAC960_LA_QueueCommandSingleMode(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + DAC960_V1_CommandMailbox_T *NextCommandMailbox = + Controller->V1.NextCommandMailbox; + CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier; + DAC960_LA_WriteCommandMailbox(NextCommandMailbox, CommandMailbox); + if (Controller->V1.PreviousCommandMailbox1->Words[0] == 0 || + Controller->V1.PreviousCommandMailbox2->Words[0] == 0) + DAC960_LA_HardwareMailboxNewCommand(ControllerBaseAddress); + Controller->V1.PreviousCommandMailbox2 = + Controller->V1.PreviousCommandMailbox1; + Controller->V1.PreviousCommandMailbox1 = NextCommandMailbox; + if (++NextCommandMailbox > Controller->V1.LastCommandMailbox) + NextCommandMailbox = Controller->V1.FirstCommandMailbox; + Controller->V1.NextCommandMailbox = NextCommandMailbox; +} + + +/* + DAC960_PG_QueueCommandDualMode queues Command for DAC960 PG Series + Controllers with Dual Mode Firmware. +*/ + +static void DAC960_PG_QueueCommandDualMode(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + DAC960_V1_CommandMailbox_T *NextCommandMailbox = + Controller->V1.NextCommandMailbox; + CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier; + DAC960_PG_WriteCommandMailbox(NextCommandMailbox, CommandMailbox); + if (Controller->V1.PreviousCommandMailbox1->Words[0] == 0 || + Controller->V1.PreviousCommandMailbox2->Words[0] == 0) + DAC960_PG_MemoryMailboxNewCommand(ControllerBaseAddress); + Controller->V1.PreviousCommandMailbox2 = + Controller->V1.PreviousCommandMailbox1; + Controller->V1.PreviousCommandMailbox1 = NextCommandMailbox; + if (++NextCommandMailbox > Controller->V1.LastCommandMailbox) + NextCommandMailbox = Controller->V1.FirstCommandMailbox; + Controller->V1.NextCommandMailbox = NextCommandMailbox; +} + + +/* + DAC960_PG_QueueCommandSingleMode queues Command for DAC960 PG Series + Controllers with Single Mode Firmware. +*/ + +static void DAC960_PG_QueueCommandSingleMode(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + DAC960_V1_CommandMailbox_T *NextCommandMailbox = + Controller->V1.NextCommandMailbox; + CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier; + DAC960_PG_WriteCommandMailbox(NextCommandMailbox, CommandMailbox); + if (Controller->V1.PreviousCommandMailbox1->Words[0] == 0 || + Controller->V1.PreviousCommandMailbox2->Words[0] == 0) + DAC960_PG_HardwareMailboxNewCommand(ControllerBaseAddress); + Controller->V1.PreviousCommandMailbox2 = + Controller->V1.PreviousCommandMailbox1; + Controller->V1.PreviousCommandMailbox1 = NextCommandMailbox; + if (++NextCommandMailbox > Controller->V1.LastCommandMailbox) + NextCommandMailbox = Controller->V1.FirstCommandMailbox; + Controller->V1.NextCommandMailbox = NextCommandMailbox; +} + + +/* + DAC960_PD_QueueCommand queues Command for DAC960 PD Series Controllers. +*/ + +static void DAC960_PD_QueueCommand(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier; + while (DAC960_PD_MailboxFullP(ControllerBaseAddress)) + udelay(1); + DAC960_PD_WriteCommandMailbox(ControllerBaseAddress, CommandMailbox); + DAC960_PD_NewCommand(ControllerBaseAddress); +} + + +/* + DAC960_ExecuteCommand executes Command and waits for completion. */ -static boolean DAC960_ExecuteCommand(DAC960_Command_T *Command) +static void DAC960_ExecuteCommand(DAC960_Command_T *Command) { DAC960_Controller_T *Controller = Command->Controller; DECLARE_MUTEX_LOCKED(Semaphore); @@ -270,227 +495,386 @@ DAC960_AcquireControllerLock(Controller, &ProcessorFlags); DAC960_QueueCommand(Command); DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - if (!in_interrupt()) - down(&Semaphore); - return Command->CommandStatus == DAC960_NormalCompletion; + if (in_interrupt()) return; + down(&Semaphore); } /* - DAC960_ExecuteType3 executes a DAC960 Type 3 Command and waits for - completion. It returns true on success and false on failure. + DAC960_V1_ExecuteType3 executes a DAC960 V1 Firmware Controller Type 3 + Command and waits for completion. It returns true on success and false + on failure. */ -static boolean DAC960_ExecuteType3(DAC960_Controller_T *Controller, - DAC960_CommandOpcode_T CommandOpcode, - void *DataPointer) +static boolean DAC960_V1_ExecuteType3(DAC960_Controller_T *Controller, + DAC960_V1_CommandOpcode_T CommandOpcode, + void *DataPointer) { DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; - boolean Result; - DAC960_ClearCommand(Command); + DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + DAC960_V1_CommandStatus_T CommandStatus; + DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; CommandMailbox->Type3.CommandOpcode = CommandOpcode; CommandMailbox->Type3.BusAddress = Virtual_to_Bus(DataPointer); - Result = DAC960_ExecuteCommand(Command); + DAC960_ExecuteCommand(Command); + CommandStatus = Command->V1.CommandStatus; DAC960_DeallocateCommand(Command); - return Result; + return (CommandStatus == DAC960_V1_NormalCompletion); } /* - DAC960_ExecuteType3D executes a DAC960 Type 3D Command and waits for - completion. It returns true on success and false on failure. + DAC960_V1_ExecuteType3D executes a DAC960 V1 Firmware Controller Type 3D + Command and waits for completion. It returns true on success and false + on failure. */ -static boolean DAC960_ExecuteType3D(DAC960_Controller_T *Controller, - DAC960_CommandOpcode_T CommandOpcode, - unsigned char Channel, - unsigned char TargetID, - void *DataPointer) +static boolean DAC960_V1_ExecuteType3D(DAC960_Controller_T *Controller, + DAC960_V1_CommandOpcode_T CommandOpcode, + unsigned char Channel, + unsigned char TargetID, + void *DataPointer) { DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; - boolean Result; - DAC960_ClearCommand(Command); + DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + DAC960_V1_CommandStatus_T CommandStatus; + DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; CommandMailbox->Type3D.CommandOpcode = CommandOpcode; CommandMailbox->Type3D.Channel = Channel; CommandMailbox->Type3D.TargetID = TargetID; CommandMailbox->Type3D.BusAddress = Virtual_to_Bus(DataPointer); - Result = DAC960_ExecuteCommand(Command); + DAC960_ExecuteCommand(Command); + CommandStatus = Command->V1.CommandStatus; DAC960_DeallocateCommand(Command); - return Result; + return (CommandStatus == DAC960_V1_NormalCompletion); } /* - DAC960_ReportErrorStatus reports Controller BIOS Messages passed through - the Error Status Register when the driver performs the BIOS handshaking. - It returns true for fatal errors and false otherwise. + DAC960_V2_GeneralInfo executes a DAC960 V2 Firmware General Information + Reading IOCTL Command and waits for completion. It returns true on success + and false on failure. */ -static boolean DAC960_ReportErrorStatus(DAC960_Controller_T *Controller, - unsigned char ErrorStatus, - unsigned char Parameter0, - unsigned char Parameter1) +static boolean DAC960_V2_GeneralInfo(DAC960_Controller_T *Controller, + DAC960_V2_IOCTL_Opcode_T IOCTL_Opcode, + void *DataPointer, + unsigned int DataByteCount) { - switch (ErrorStatus) - { - case 0x00: - DAC960_Notice("Physical Drive %d:%d Not Responding\n", - Controller, Parameter1, Parameter0); - break; - case 0x08: - if (Controller->DriveSpinUpMessageDisplayed) break; - DAC960_Notice("Spinning Up Drives\n", Controller); - Controller->DriveSpinUpMessageDisplayed = true; - break; - case 0x30: - DAC960_Notice("Configuration Checksum Error\n", Controller); - break; - case 0x60: - DAC960_Notice("Mirror Race Recovery Failed\n", Controller); - break; - case 0x70: - DAC960_Notice("Mirror Race Recovery In Progress\n", Controller); - break; - case 0x90: - DAC960_Notice("Physical Drive %d:%d COD Mismatch\n", - Controller, Parameter1, Parameter0); - break; - case 0xA0: - DAC960_Notice("Logical Drive Installation Aborted\n", Controller); - break; - case 0xB0: - DAC960_Notice("Mirror Race On A Critical Logical Drive\n", Controller); - break; - case 0xD0: - DAC960_Notice("New Controller Configuration Found\n", Controller); - break; - case 0xF0: - DAC960_Error("Fatal Memory Parity Error for Controller at\n", Controller); - return true; - default: - DAC960_Error("Unknown Initialization Error %02X for Controller at\n", - Controller, ErrorStatus); - return true; - } - return false; + DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); + DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_CommandStatus_T CommandStatus; + DAC960_V2_ClearCommand(Command); + Command->CommandType = DAC960_ImmediateCommand; + CommandMailbox->Common.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->Common.CommandControlBits + .DataTransferControllerToHost = true; + CommandMailbox->Common.CommandControlBits + .NoAutoRequestSense = true; + CommandMailbox->Common.DataTransferSize = DataByteCount; + CommandMailbox->Common.IOCTL_Opcode = IOCTL_Opcode; + CommandMailbox->Common.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(DataPointer); + CommandMailbox->Common.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->Common.DataTransferSize; + DAC960_ExecuteCommand(Command); + CommandStatus = Command->V2.CommandStatus; + DAC960_DeallocateCommand(Command); + return (CommandStatus == DAC960_V2_NormalCompletion); } /* - DAC960_EnableMemoryMailboxInterface enables the Memory Mailbox Interface. + DAC960_V2_ControllerInfo executes a DAC960 V2 Firmware Controller + Information Reading IOCTL Command and waits for completion. It returns + true on success and false on failure. */ -static boolean DAC960_EnableMemoryMailboxInterface(DAC960_Controller_T - *Controller) +static boolean DAC960_V2_ControllerInfo(DAC960_Controller_T *Controller, + DAC960_V2_IOCTL_Opcode_T IOCTL_Opcode, + void *DataPointer, + unsigned int DataByteCount) +{ + DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); + DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_CommandStatus_T CommandStatus; + DAC960_V2_ClearCommand(Command); + Command->CommandType = DAC960_ImmediateCommand; + CommandMailbox->ControllerInfo.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->ControllerInfo.CommandControlBits + .DataTransferControllerToHost = true; + CommandMailbox->ControllerInfo.CommandControlBits + .NoAutoRequestSense = true; + CommandMailbox->ControllerInfo.DataTransferSize = DataByteCount; + CommandMailbox->ControllerInfo.ControllerNumber = 0; + CommandMailbox->ControllerInfo.IOCTL_Opcode = IOCTL_Opcode; + CommandMailbox->ControllerInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(DataPointer); + CommandMailbox->ControllerInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->ControllerInfo.DataTransferSize; + DAC960_ExecuteCommand(Command); + CommandStatus = Command->V2.CommandStatus; + DAC960_DeallocateCommand(Command); + return (CommandStatus == DAC960_V2_NormalCompletion); +} + + +/* + DAC960_V2_LogicalDeviceInfo executes a DAC960 V2 Firmware Controller Logical + Device Information Reading IOCTL Command and waits for completion. It + returns true on success and false on failure. +*/ + +static boolean DAC960_V2_LogicalDeviceInfo(DAC960_Controller_T *Controller, + DAC960_V2_IOCTL_Opcode_T + IOCTL_Opcode, + unsigned short + LogicalDeviceNumber, + void *DataPointer, + unsigned int DataByteCount) +{ + DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); + DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_CommandStatus_T CommandStatus; + DAC960_V2_ClearCommand(Command); + Command->CommandType = DAC960_ImmediateCommand; + CommandMailbox->LogicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->LogicalDeviceInfo.CommandControlBits + .DataTransferControllerToHost = true; + CommandMailbox->LogicalDeviceInfo.CommandControlBits + .NoAutoRequestSense = true; + CommandMailbox->LogicalDeviceInfo.DataTransferSize = DataByteCount; + CommandMailbox->LogicalDeviceInfo.LogicalDevice.LogicalDeviceNumber = + LogicalDeviceNumber; + CommandMailbox->LogicalDeviceInfo.IOCTL_Opcode = IOCTL_Opcode; + CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(DataPointer); + CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->LogicalDeviceInfo.DataTransferSize; + DAC960_ExecuteCommand(Command); + CommandStatus = Command->V2.CommandStatus; + DAC960_DeallocateCommand(Command); + return (CommandStatus == DAC960_V2_NormalCompletion); +} + + +/* + DAC960_V2_PhysicalDeviceInfo executes a DAC960 V2 Firmware Controller Physical + Device Information Reading IOCTL Command and waits for completion. It + returns true on success and false on failure. +*/ + +static boolean DAC960_V2_PhysicalDeviceInfo(DAC960_Controller_T *Controller, + DAC960_V2_IOCTL_Opcode_T + IOCTL_Opcode, + unsigned char Channel, + unsigned char TargetID, + unsigned char LogicalUnit, + void *DataPointer, + unsigned int DataByteCount) +{ + DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); + DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_CommandStatus_T CommandStatus; + DAC960_V2_ClearCommand(Command); + Command->CommandType = DAC960_ImmediateCommand; + CommandMailbox->PhysicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->PhysicalDeviceInfo.CommandControlBits + .DataTransferControllerToHost = true; + CommandMailbox->PhysicalDeviceInfo.CommandControlBits + .NoAutoRequestSense = true; + CommandMailbox->PhysicalDeviceInfo.DataTransferSize = DataByteCount; + CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.LogicalUnit = LogicalUnit; + CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.TargetID = TargetID; + CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.Channel = Channel; + CommandMailbox->PhysicalDeviceInfo.IOCTL_Opcode = IOCTL_Opcode; + CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(DataPointer); + CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->PhysicalDeviceInfo.DataTransferSize; + DAC960_ExecuteCommand(Command); + CommandStatus = Command->V2.CommandStatus; + DAC960_DeallocateCommand(Command); + return (CommandStatus == DAC960_V2_NormalCompletion); +} + + +/* + DAC960_V2_DeviceOperation executes a DAC960 V2 Firmware Controller Device + Operation IOCTL Command and waits for completion. It returns true on + success and false on failure. +*/ + +static boolean DAC960_V2_DeviceOperation(DAC960_Controller_T *Controller, + DAC960_V2_IOCTL_Opcode_T IOCTL_Opcode, + DAC960_V2_OperationDevice_T + OperationDevice) +{ + DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); + DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_CommandStatus_T CommandStatus; + DAC960_V2_ClearCommand(Command); + Command->CommandType = DAC960_ImmediateCommand; + CommandMailbox->DeviceOperation.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->DeviceOperation.CommandControlBits + .DataTransferControllerToHost = true; + CommandMailbox->DeviceOperation.CommandControlBits + .NoAutoRequestSense = true; + CommandMailbox->DeviceOperation.IOCTL_Opcode = IOCTL_Opcode; + CommandMailbox->DeviceOperation.OperationDevice = OperationDevice; + DAC960_ExecuteCommand(Command); + CommandStatus = Command->V2.CommandStatus; + DAC960_DeallocateCommand(Command); + return (CommandStatus == DAC960_V2_NormalCompletion); +} + + +/* + DAC960_V1_EnableMemoryMailboxInterface enables the Memory Mailbox Interface + for DAC960 V1 Firmware Controllers. +*/ + +static boolean DAC960_V1_EnableMemoryMailboxInterface(DAC960_Controller_T + *Controller) { void *ControllerBaseAddress = Controller->BaseAddress; - DAC960_CommandMailbox_T *CommandMailboxesMemory; - DAC960_StatusMailbox_T *StatusMailboxesMemory; - DAC960_CommandMailbox_T CommandMailbox; - DAC960_CommandStatus_T CommandStatus; + DAC960_V1_CommandMailbox_T *CommandMailboxesMemory; + DAC960_V1_StatusMailbox_T *StatusMailboxesMemory; + DAC960_V1_CommandMailbox_T CommandMailbox; + DAC960_V1_CommandStatus_T CommandStatus; + unsigned long MemoryMailboxPagesAddress; + unsigned long MemoryMailboxPagesOrder; + unsigned long MemoryMailboxPagesSize; void *SavedMemoryMailboxesAddress = NULL; short NextCommandMailboxIndex = 0; short NextStatusMailboxIndex = 0; int TimeoutCounter = 1000000, i; - if (Controller->ControllerType == DAC960_V5_Controller) - DAC960_V5_RestoreMemoryMailboxInfo(Controller, + MemoryMailboxPagesOrder = 0; + MemoryMailboxPagesSize = + DAC960_V1_CommandMailboxCount * sizeof(DAC960_V1_CommandMailbox_T) + + DAC960_V1_StatusMailboxCount * sizeof(DAC960_V1_StatusMailbox_T); + while (MemoryMailboxPagesSize > PAGE_SIZE << MemoryMailboxPagesOrder) + MemoryMailboxPagesOrder++; + if (Controller->HardwareType == DAC960_LA_Controller) + DAC960_LA_RestoreMemoryMailboxInfo(Controller, &SavedMemoryMailboxesAddress, &NextCommandMailboxIndex, &NextStatusMailboxIndex); - else DAC960_V4_RestoreMemoryMailboxInfo(Controller, + else DAC960_PG_RestoreMemoryMailboxInfo(Controller, &SavedMemoryMailboxesAddress, &NextCommandMailboxIndex, &NextStatusMailboxIndex); if (SavedMemoryMailboxesAddress == NULL) - CommandMailboxesMemory = - (DAC960_CommandMailbox_T *) __get_free_pages(GFP_KERNEL, 1); + { + MemoryMailboxPagesAddress = + __get_free_pages(GFP_KERNEL, MemoryMailboxPagesOrder); + Controller->MemoryMailboxPagesAddress = MemoryMailboxPagesAddress; + CommandMailboxesMemory = + (DAC960_V1_CommandMailbox_T *) MemoryMailboxPagesAddress; + } else CommandMailboxesMemory = SavedMemoryMailboxesAddress; - memset(CommandMailboxesMemory, 0, PAGE_SIZE << 1); - Controller->FirstCommandMailbox = CommandMailboxesMemory; - CommandMailboxesMemory += DAC960_CommandMailboxCount - 1; - Controller->LastCommandMailbox = CommandMailboxesMemory; - Controller->NextCommandMailbox = - &Controller->FirstCommandMailbox[NextCommandMailboxIndex]; + if (CommandMailboxesMemory == NULL) return false; + Controller->MemoryMailboxPagesOrder = MemoryMailboxPagesOrder; + memset(CommandMailboxesMemory, 0, MemoryMailboxPagesSize); + Controller->V1.FirstCommandMailbox = CommandMailboxesMemory; + CommandMailboxesMemory += DAC960_V1_CommandMailboxCount - 1; + Controller->V1.LastCommandMailbox = CommandMailboxesMemory; + Controller->V1.NextCommandMailbox = + &Controller->V1.FirstCommandMailbox[NextCommandMailboxIndex]; if (--NextCommandMailboxIndex < 0) - NextCommandMailboxIndex = DAC960_CommandMailboxCount - 1; - Controller->PreviousCommandMailbox1 = - &Controller->FirstCommandMailbox[NextCommandMailboxIndex]; + NextCommandMailboxIndex = DAC960_V1_CommandMailboxCount - 1; + Controller->V1.PreviousCommandMailbox1 = + &Controller->V1.FirstCommandMailbox[NextCommandMailboxIndex]; if (--NextCommandMailboxIndex < 0) - NextCommandMailboxIndex = DAC960_CommandMailboxCount - 1; - Controller->PreviousCommandMailbox2 = - &Controller->FirstCommandMailbox[NextCommandMailboxIndex]; + NextCommandMailboxIndex = DAC960_V1_CommandMailboxCount - 1; + Controller->V1.PreviousCommandMailbox2 = + &Controller->V1.FirstCommandMailbox[NextCommandMailboxIndex]; StatusMailboxesMemory = - (DAC960_StatusMailbox_T *) (CommandMailboxesMemory + 1); - Controller->FirstStatusMailbox = StatusMailboxesMemory; - StatusMailboxesMemory += DAC960_StatusMailboxCount - 1; - Controller->LastStatusMailbox = StatusMailboxesMemory; - Controller->NextStatusMailbox = - &Controller->FirstStatusMailbox[NextStatusMailboxIndex]; + (DAC960_V1_StatusMailbox_T *) (CommandMailboxesMemory + 1); + Controller->V1.FirstStatusMailbox = StatusMailboxesMemory; + StatusMailboxesMemory += DAC960_V1_StatusMailboxCount - 1; + Controller->V1.LastStatusMailbox = StatusMailboxesMemory; + Controller->V1.NextStatusMailbox = + &Controller->V1.FirstStatusMailbox[NextStatusMailboxIndex]; if (SavedMemoryMailboxesAddress != NULL) return true; /* Enable the Memory Mailbox Interface. */ - Controller->DualModeMemoryMailboxInterface = true; + Controller->V1.DualModeMemoryMailboxInterface = true; CommandMailbox.TypeX.CommandOpcode = 0x2B; CommandMailbox.TypeX.CommandIdentifier = 0; CommandMailbox.TypeX.CommandOpcode2 = 0x14; CommandMailbox.TypeX.CommandMailboxesBusAddress = - Virtual_to_Bus(Controller->FirstCommandMailbox); + Virtual_to_Bus(Controller->V1.FirstCommandMailbox); CommandMailbox.TypeX.StatusMailboxesBusAddress = - Virtual_to_Bus(Controller->FirstStatusMailbox); + Virtual_to_Bus(Controller->V1.FirstStatusMailbox); for (i = 0; i < 2; i++) - switch (Controller->ControllerType) + switch (Controller->HardwareType) { - case DAC960_V5_Controller: + case DAC960_LA_Controller: while (--TimeoutCounter >= 0) { - if (!DAC960_V5_HardwareMailboxFullP(ControllerBaseAddress)) + if (!DAC960_LA_HardwareMailboxFullP(ControllerBaseAddress)) break; udelay(10); } if (TimeoutCounter < 0) return false; - DAC960_V5_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); - DAC960_V5_HardwareMailboxNewCommand(ControllerBaseAddress); + DAC960_LA_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); + DAC960_LA_HardwareMailboxNewCommand(ControllerBaseAddress); while (--TimeoutCounter >= 0) { - if (DAC960_V5_HardwareMailboxStatusAvailableP( + if (DAC960_LA_HardwareMailboxStatusAvailableP( ControllerBaseAddress)) break; udelay(10); } if (TimeoutCounter < 0) return false; - CommandStatus = DAC960_V5_ReadStatusRegister(ControllerBaseAddress); - DAC960_V5_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress); - DAC960_V5_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress); - if (CommandStatus == DAC960_NormalCompletion) return true; - Controller->DualModeMemoryMailboxInterface = false; + CommandStatus = DAC960_LA_ReadStatusRegister(ControllerBaseAddress); + DAC960_LA_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress); + DAC960_LA_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress); + if (CommandStatus == DAC960_V1_NormalCompletion) return true; + Controller->V1.DualModeMemoryMailboxInterface = false; CommandMailbox.TypeX.CommandOpcode2 = 0x10; break; - case DAC960_V4_Controller: + case DAC960_PG_Controller: while (--TimeoutCounter >= 0) { - if (!DAC960_V4_HardwareMailboxFullP(ControllerBaseAddress)) + if (!DAC960_PG_HardwareMailboxFullP(ControllerBaseAddress)) break; udelay(10); } if (TimeoutCounter < 0) return false; - DAC960_V4_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); - DAC960_V4_HardwareMailboxNewCommand(ControllerBaseAddress); + DAC960_PG_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); + DAC960_PG_HardwareMailboxNewCommand(ControllerBaseAddress); while (--TimeoutCounter >= 0) { - if (DAC960_V4_HardwareMailboxStatusAvailableP( + if (DAC960_PG_HardwareMailboxStatusAvailableP( ControllerBaseAddress)) break; udelay(10); } if (TimeoutCounter < 0) return false; - CommandStatus = DAC960_V4_ReadStatusRegister(ControllerBaseAddress); - DAC960_V4_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress); - DAC960_V4_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress); - if (CommandStatus == DAC960_NormalCompletion) return true; - Controller->DualModeMemoryMailboxInterface = false; + CommandStatus = DAC960_PG_ReadStatusRegister(ControllerBaseAddress); + DAC960_PG_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress); + DAC960_PG_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress); + if (CommandStatus == DAC960_V1_NormalCompletion) return true; + Controller->V1.DualModeMemoryMailboxInterface = false; CommandMailbox.TypeX.CommandOpcode2 = 0x10; break; default: @@ -501,287 +885,165 @@ /* - DAC960_DetectControllers detects DAC960 PCI RAID Controllers by interrogating - the PCI Configuration Space for Controller Type. + DAC960_V2_EnableMemoryMailboxInterface enables the Memory Mailbox Interface + for DAC960 V2 Firmware Controllers. */ -static void DAC960_DetectControllers(DAC960_ControllerType_T ControllerType) +static boolean DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T + *Controller) { - unsigned short VendorID = 0, DeviceID = 0; - unsigned int MemoryWindowSize = 0; - PCI_Device_T *PCI_Device = NULL; - switch (ControllerType) + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_V2_CommandMailbox_T *CommandMailboxesMemory; + DAC960_V2_StatusMailbox_T *StatusMailboxesMemory; + DAC960_V2_CommandMailbox_T CommandMailbox; + DAC960_V2_CommandStatus_T CommandStatus = 0; + unsigned long MemoryMailboxPagesAddress; + unsigned long MemoryMailboxPagesOrder; + unsigned long MemoryMailboxPagesSize; + MemoryMailboxPagesOrder = 0; + MemoryMailboxPagesSize = + DAC960_V2_CommandMailboxCount * sizeof(DAC960_V2_CommandMailbox_T) + + DAC960_V2_StatusMailboxCount * sizeof(DAC960_V2_StatusMailbox_T) + + sizeof(DAC960_V2_HealthStatusBuffer_T); + while (MemoryMailboxPagesSize > PAGE_SIZE << MemoryMailboxPagesOrder) + MemoryMailboxPagesOrder++; + MemoryMailboxPagesAddress = + __get_free_pages(GFP_KERNEL, MemoryMailboxPagesOrder); + Controller->MemoryMailboxPagesAddress = MemoryMailboxPagesAddress; + CommandMailboxesMemory = + (DAC960_V2_CommandMailbox_T *) MemoryMailboxPagesAddress; + if (CommandMailboxesMemory == NULL) return false; + Controller->MemoryMailboxPagesOrder = MemoryMailboxPagesOrder; + memset(CommandMailboxesMemory, 0, MemoryMailboxPagesSize); + Controller->V2.FirstCommandMailbox = CommandMailboxesMemory; + CommandMailboxesMemory += DAC960_V2_CommandMailboxCount - 1; + Controller->V2.LastCommandMailbox = CommandMailboxesMemory; + Controller->V2.NextCommandMailbox = Controller->V2.FirstCommandMailbox; + Controller->V2.PreviousCommandMailbox1 = Controller->V2.LastCommandMailbox; + Controller->V2.PreviousCommandMailbox2 = + Controller->V2.LastCommandMailbox - 1; + StatusMailboxesMemory = + (DAC960_V2_StatusMailbox_T *) (CommandMailboxesMemory + 1); + Controller->V2.FirstStatusMailbox = StatusMailboxesMemory; + StatusMailboxesMemory += DAC960_V2_StatusMailboxCount - 1; + Controller->V2.LastStatusMailbox = StatusMailboxesMemory; + Controller->V2.NextStatusMailbox = Controller->V2.FirstStatusMailbox; + Controller->V2.HealthStatusBuffer = + (DAC960_V2_HealthStatusBuffer_T *) (StatusMailboxesMemory + 1); + /* Enable the Memory Mailbox Interface. */ + memset(&CommandMailbox, 0, sizeof(DAC960_V2_CommandMailbox_T)); + CommandMailbox.SetMemoryMailbox.CommandIdentifier = 1; + CommandMailbox.SetMemoryMailbox.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox.SetMemoryMailbox.CommandControlBits.NoAutoRequestSense = true; + CommandMailbox.SetMemoryMailbox.FirstCommandMailboxSizeKB = + (DAC960_V2_CommandMailboxCount * sizeof(DAC960_V2_CommandMailbox_T)) >> 10; + CommandMailbox.SetMemoryMailbox.FirstStatusMailboxSizeKB = + (DAC960_V2_StatusMailboxCount * sizeof(DAC960_V2_StatusMailbox_T)) >> 10; + CommandMailbox.SetMemoryMailbox.SecondCommandMailboxSizeKB = 0; + CommandMailbox.SetMemoryMailbox.SecondStatusMailboxSizeKB = 0; + CommandMailbox.SetMemoryMailbox.RequestSenseSize = 0; + CommandMailbox.SetMemoryMailbox.IOCTL_Opcode = DAC960_V2_SetMemoryMailbox; + CommandMailbox.SetMemoryMailbox.HealthStatusBufferSizeKB = 1; + CommandMailbox.SetMemoryMailbox.HealthStatusBufferBusAddress = + Virtual_to_Bus(Controller->V2.HealthStatusBuffer); + CommandMailbox.SetMemoryMailbox.FirstCommandMailboxBusAddress = + Virtual_to_Bus(Controller->V2.FirstCommandMailbox); + CommandMailbox.SetMemoryMailbox.FirstStatusMailboxBusAddress = + Virtual_to_Bus(Controller->V2.FirstStatusMailbox); + switch (Controller->HardwareType) { - case DAC960_V5_Controller: - VendorID = PCI_VENDOR_ID_DEC; - DeviceID = PCI_DEVICE_ID_DEC_21285; - MemoryWindowSize = DAC960_V5_RegisterWindowSize; + case DAC960_BA_Controller: + while (DAC960_BA_HardwareMailboxFullP(ControllerBaseAddress)) + udelay(1); + DAC960_BA_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); + DAC960_BA_HardwareMailboxNewCommand(ControllerBaseAddress); + while (!DAC960_BA_HardwareMailboxStatusAvailableP(ControllerBaseAddress)) + udelay(1); + CommandStatus = DAC960_BA_ReadCommandStatus(ControllerBaseAddress); + DAC960_BA_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress); + DAC960_BA_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress); break; - case DAC960_V4_Controller: - VendorID = PCI_VENDOR_ID_MYLEX; - DeviceID = PCI_DEVICE_ID_MYLEX_DAC960P_V4; - MemoryWindowSize = DAC960_V4_RegisterWindowSize; + case DAC960_LP_Controller: + while (DAC960_LP_HardwareMailboxFullP(ControllerBaseAddress)) + udelay(1); + DAC960_LP_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); + DAC960_LP_HardwareMailboxNewCommand(ControllerBaseAddress); + while (!DAC960_LP_HardwareMailboxStatusAvailableP(ControllerBaseAddress)) + udelay(1); + CommandStatus = DAC960_LP_ReadCommandStatus(ControllerBaseAddress); + DAC960_LP_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress); + DAC960_LP_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress); break; - case DAC960_V3_Controller: - VendorID = PCI_VENDOR_ID_MYLEX; - DeviceID = PCI_DEVICE_ID_MYLEX_DAC960P_V3; - MemoryWindowSize = DAC960_V3_RegisterWindowSize; + default: break; } - while ((PCI_Device = pci_find_device(VendorID, DeviceID, PCI_Device)) != NULL) - { - DAC960_Controller_T *Controller = (DAC960_Controller_T *) - kmalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC); - DAC960_IO_Address_T IO_Address = 0; - DAC960_PCI_Address_T PCI_Address = 0; - unsigned char Bus = PCI_Device->bus->number; - unsigned char DeviceFunction = PCI_Device->devfn; - unsigned char Device = DeviceFunction >> 3; - unsigned char Function = DeviceFunction & 0x7; - unsigned int IRQ_Channel = PCI_Device->irq; - unsigned long BaseAddress0 = pci_resource_start (PCI_Device, 0); - unsigned long BaseAddress1 = pci_resource_start (PCI_Device, 1); - unsigned short SubsystemVendorID, SubsystemDeviceID; - int CommandIdentifier; - unsigned char ErrorStatus, Parameter0, Parameter1; - void *BaseAddress; + return (CommandStatus == DAC960_V2_NormalCompletion); +} - if (pci_enable_device(PCI_Device)) - goto Ignore; +/* + DAC960_V1_ReadControllerConfiguration reads the Configuration Information + from DAC960 V1 Firmware Controllers and initializes the Controller structure. +*/ - SubsystemVendorID = PCI_Device->subsystem_vendor; - SubsystemDeviceID = PCI_Device->subsystem_device; - switch (ControllerType) - { - case DAC960_V5_Controller: - if (!(SubsystemVendorID == PCI_VENDOR_ID_MYLEX && - SubsystemDeviceID == PCI_DEVICE_ID_MYLEX_DAC960P_V5)) - goto Ignore; - PCI_Address = BaseAddress0; - break; - case DAC960_V4_Controller: - PCI_Address = BaseAddress0; - break; - case DAC960_V3_Controller: - IO_Address = BaseAddress0; - PCI_Address = BaseAddress1; - break; - } - if (DAC960_ControllerCount == DAC960_MaxControllers) - { - DAC960_Error("More than %d DAC960 Controllers detected - " - "ignoring from Controller at\n", - NULL, DAC960_MaxControllers); - goto Ignore; - } - if (Controller == NULL) - { - DAC960_Error("Unable to allocate Controller structure for " - "Controller at\n", NULL); - goto Ignore; - } - memset(Controller, 0, sizeof(DAC960_Controller_T)); - init_waitqueue_head(&Controller->CommandWaitQueue); - Controller->ControllerNumber = DAC960_ControllerCount; - DAC960_Controllers[DAC960_ControllerCount++] = Controller; - DAC960_AnnounceDriver(Controller); - Controller->ControllerType = ControllerType; - Controller->IO_Address = IO_Address; - Controller->PCI_Address = PCI_Address; - Controller->Bus = Bus; - Controller->Device = Device; - Controller->Function = Function; - sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber); - /* - Map the Controller Register Window. - */ - if (MemoryWindowSize < PAGE_SIZE) - MemoryWindowSize = PAGE_SIZE; - Controller->MemoryMappedAddress = - ioremap_nocache(PCI_Address & PAGE_MASK, MemoryWindowSize); - Controller->BaseAddress = - Controller->MemoryMappedAddress + (PCI_Address & ~PAGE_MASK); - if (Controller->MemoryMappedAddress == NULL) - { - DAC960_Error("Unable to map Controller Register Window for " - "Controller at\n", Controller); - goto Failure; - } - BaseAddress = Controller->BaseAddress; - switch (ControllerType) - { - case DAC960_V5_Controller: - DAC960_V5_DisableInterrupts(BaseAddress); - DAC960_V5_AcknowledgeHardwareMailboxStatus(BaseAddress); - udelay(1000); - while (DAC960_V5_InitializationInProgressP(BaseAddress)) - { - if (DAC960_V5_ReadErrorStatus(BaseAddress, &ErrorStatus, - &Parameter0, &Parameter1) && - DAC960_ReportErrorStatus(Controller, ErrorStatus, - Parameter0, Parameter1)) - goto Failure; - udelay(10); - } - if (!DAC960_EnableMemoryMailboxInterface(Controller)) - { - DAC960_Error("Unable to Enable Memory Mailbox Interface " - "for Controller at\n", Controller); - goto Failure; - } - DAC960_V5_EnableInterrupts(BaseAddress); - break; - case DAC960_V4_Controller: - DAC960_V4_DisableInterrupts(BaseAddress); - DAC960_V4_AcknowledgeHardwareMailboxStatus(BaseAddress); - udelay(1000); - while (DAC960_V4_InitializationInProgressP(BaseAddress)) - { - if (DAC960_V4_ReadErrorStatus(BaseAddress, &ErrorStatus, - &Parameter0, &Parameter1) && - DAC960_ReportErrorStatus(Controller, ErrorStatus, - Parameter0, Parameter1)) - goto Failure; - udelay(10); - } - if (!DAC960_EnableMemoryMailboxInterface(Controller)) - { - DAC960_Error("Unable to Enable Memory Mailbox Interface " - "for Controller at\n", Controller); - goto Failure; - } - DAC960_V4_EnableInterrupts(BaseAddress); - break; - case DAC960_V3_Controller: - request_region(Controller->IO_Address, 0x80, - Controller->FullModelName); - DAC960_V3_DisableInterrupts(BaseAddress); - DAC960_V3_AcknowledgeStatus(BaseAddress); - udelay(1000); - while (DAC960_V3_InitializationInProgressP(BaseAddress)) - { - if (DAC960_V3_ReadErrorStatus(BaseAddress, &ErrorStatus, - &Parameter0, &Parameter1) && - DAC960_ReportErrorStatus(Controller, ErrorStatus, - Parameter0, Parameter1)) - goto Failure; - udelay(10); - } - DAC960_V3_EnableInterrupts(BaseAddress); - break; - } - /* - Acquire shared access to the IRQ Channel. - */ - if (IRQ_Channel == 0) - { - DAC960_Error("IRQ Channel %d illegal for Controller at\n", - Controller, IRQ_Channel); - goto Failure; - } - strcpy(Controller->FullModelName, "DAC960"); - if (request_irq(IRQ_Channel, DAC960_InterruptHandler, - SA_SHIRQ, Controller->FullModelName, Controller) < 0) - { - DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n", - Controller, IRQ_Channel); - goto Failure; - } - Controller->IRQ_Channel = IRQ_Channel; - DAC960_ActiveControllerCount++; - for (CommandIdentifier = 0; - CommandIdentifier < DAC960_MaxChannels; - CommandIdentifier++) - { - Controller->Commands[CommandIdentifier].Controller = Controller; - Controller->Commands[CommandIdentifier].Next = - Controller->FreeCommands; - Controller->FreeCommands = &Controller->Commands[CommandIdentifier]; - } - continue; - Failure: - if (IO_Address == 0) - DAC960_Error("PCI Bus %d Device %d Function %d I/O Address N/A " - "PCI Address 0x%X\n", Controller, - Bus, Device, Function, PCI_Address); - else DAC960_Error("PCI Bus %d Device %d Function %d I/O Address " - "0x%X PCI Address 0x%X\n", Controller, - Bus, Device, Function, IO_Address, PCI_Address); - if (Controller == NULL) break; - if (Controller->MemoryMappedAddress != NULL) - iounmap(Controller->MemoryMappedAddress); - DAC960_Controllers[Controller->ControllerNumber] = NULL; - if (Controller->IRQ_Channel > 0) - free_irq(IRQ_Channel, Controller); - Ignore: - kfree(Controller); - } -} - - -/* - DAC960_ReadControllerConfiguration reads the Configuration Information - from Controller and initializes the Controller structure. -*/ - -static boolean DAC960_ReadControllerConfiguration(DAC960_Controller_T - *Controller) +static boolean DAC960_V1_ReadControllerConfiguration(DAC960_Controller_T + *Controller) { - DAC960_Enquiry2_T Enquiry2; - DAC960_Config2_T Config2; + DAC960_V1_Enquiry2_T Enquiry2; + DAC960_V1_Config2_T Config2; int LogicalDriveNumber, Channel, TargetID; - if (!DAC960_ExecuteType3(Controller, DAC960_Enquiry, - &Controller->Enquiry[0])) + if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_Enquiry, + &Controller->V1.Enquiry)) return DAC960_Failure(Controller, "ENQUIRY"); - if (!DAC960_ExecuteType3(Controller, DAC960_Enquiry2, &Enquiry2)) + if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_Enquiry2, &Enquiry2)) return DAC960_Failure(Controller, "ENQUIRY2"); - if (!DAC960_ExecuteType3(Controller, DAC960_ReadConfig2, &Config2)) + if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_ReadConfig2, &Config2)) return DAC960_Failure(Controller, "READ CONFIG2"); - if (!DAC960_ExecuteType3(Controller, DAC960_GetLogicalDriveInformation, - &Controller->LogicalDriveInformation[0])) + if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_GetLogicalDriveInformation, + &Controller->V1.LogicalDriveInformation)) return DAC960_Failure(Controller, "GET LOGICAL DRIVE INFORMATION"); for (Channel = 0; Channel < Enquiry2.ActualChannels; Channel++) - for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++) - if (!DAC960_ExecuteType3D(Controller, DAC960_GetDeviceState, - Channel, TargetID, - &Controller->DeviceState[0][Channel][TargetID])) + for (TargetID = 0; TargetID < Enquiry2.MaxTargets; TargetID++) + if (!DAC960_V1_ExecuteType3D(Controller, DAC960_V1_GetDeviceState, + Channel, TargetID, + &Controller->V1.DeviceState + [Channel][TargetID])) return DAC960_Failure(Controller, "GET DEVICE STATE"); /* Initialize the Controller Model Name and Full Model Name fields. */ switch (Enquiry2.HardwareID.SubModel) { - case DAC960_P_PD_PU: - if (Enquiry2.SCSICapability.BusSpeed == DAC960_Ultra) + case DAC960_V1_P_PD_PU: + if (Enquiry2.SCSICapability.BusSpeed == DAC960_V1_Ultra) strcpy(Controller->ModelName, "DAC960PU"); else strcpy(Controller->ModelName, "DAC960PD"); break; - case DAC960_PL: + case DAC960_V1_PL: strcpy(Controller->ModelName, "DAC960PL"); break; - case DAC960_PG: + case DAC960_V1_PG: strcpy(Controller->ModelName, "DAC960PG"); break; - case DAC960_PJ: + case DAC960_V1_PJ: strcpy(Controller->ModelName, "DAC960PJ"); break; - case DAC960_PR: + case DAC960_V1_PR: strcpy(Controller->ModelName, "DAC960PR"); break; - case DAC960_PT: + case DAC960_V1_PT: strcpy(Controller->ModelName, "DAC960PT"); break; - case DAC960_PTL0: + case DAC960_V1_PTL0: strcpy(Controller->ModelName, "DAC960PTL0"); break; - case DAC960_PRL: + case DAC960_V1_PRL: strcpy(Controller->ModelName, "DAC960PRL"); break; - case DAC960_PTL1: + case DAC960_V1_PTL1: strcpy(Controller->ModelName, "DAC960PTL1"); break; - case DAC1164_P: + case DAC960_V1_1164P: strcpy(Controller->ModelName, "DAC1164P"); break; default: @@ -813,61 +1075,197 @@ return false; } /* - Initialize the Controller Channels, Memory Size, and SAF-TE Enclosure - Management Enabled fields. + Initialize the Controller Channels, Targets, Memory Size, and SAF-TE + Enclosure Management Enabled fields. */ Controller->Channels = Enquiry2.ActualChannels; + Controller->Targets = Enquiry2.MaxTargets; Controller->MemorySize = Enquiry2.MemorySize >> 20; - Controller->SAFTE_EnclosureManagementEnabled = - Enquiry2.FaultManagementType == DAC960_SAFTE; + Controller->V1.SAFTE_EnclosureManagementEnabled = + (Enquiry2.FaultManagementType == DAC960_V1_SAFTE); /* Initialize the Controller Queue Depth, Driver Queue Depth, Logical Drive - Count, Maximum Blocks per Command, and Maximum Scatter/Gather Segments. - The Driver Queue Depth must be at most one less than the Controller Queue - Depth to allow for an automatic drive rebuild operation. + Count, Maximum Blocks per Command, Controller Scatter/Gather Limit, and + Driver Scatter/Gather Limit. The Driver Queue Depth must be at most one + less than the Controller Queue Depth to allow for an automatic drive + rebuild operation. */ - Controller->ControllerQueueDepth = Controller->Enquiry[0].MaxCommands; + Controller->ControllerQueueDepth = Controller->V1.Enquiry.MaxCommands; Controller->DriverQueueDepth = Controller->ControllerQueueDepth - 1; - Controller->LogicalDriveCount = Controller->Enquiry[0].NumberOfLogicalDrives; + if (Controller->DriverQueueDepth > DAC960_MaxDriverQueueDepth) + Controller->DriverQueueDepth = DAC960_MaxDriverQueueDepth; + Controller->LogicalDriveCount = + Controller->V1.Enquiry.NumberOfLogicalDrives; Controller->MaxBlocksPerCommand = Enquiry2.MaxBlocksPerCommand; - Controller->MaxScatterGatherSegments = Enquiry2.MaxScatterGatherEntries; + Controller->ControllerScatterGatherLimit = Enquiry2.MaxScatterGatherEntries; + Controller->DriverScatterGatherLimit = + Controller->ControllerScatterGatherLimit; + if (Controller->DriverScatterGatherLimit > DAC960_V1_ScatterGatherLimit) + Controller->DriverScatterGatherLimit = DAC960_V1_ScatterGatherLimit; /* Initialize the Stripe Size, Segment Size, and Geometry Translation. */ - Controller->StripeSize = Config2.BlocksPerStripe * Config2.BlockFactor - >> (10 - DAC960_BlockSizeBits); - Controller->SegmentSize = Config2.BlocksPerCacheLine * Config2.BlockFactor - >> (10 - DAC960_BlockSizeBits); + Controller->V1.StripeSize = Config2.BlocksPerStripe * Config2.BlockFactor + >> (10 - DAC960_BlockSizeBits); + Controller->V1.SegmentSize = Config2.BlocksPerCacheLine * Config2.BlockFactor + >> (10 - DAC960_BlockSizeBits); switch (Config2.DriveGeometry) { - case DAC960_Geometry_128_32: - Controller->GeometryTranslationHeads = 128; - Controller->GeometryTranslationSectors = 32; - break; - case DAC960_Geometry_255_63: - Controller->GeometryTranslationHeads = 255; - Controller->GeometryTranslationSectors = 63; + case DAC960_V1_Geometry_128_32: + Controller->V1.GeometryTranslationHeads = 128; + Controller->V1.GeometryTranslationSectors = 32; + break; + case DAC960_V1_Geometry_255_63: + Controller->V1.GeometryTranslationHeads = 255; + Controller->V1.GeometryTranslationSectors = 63; break; default: return DAC960_Failure(Controller, "CONFIG2 DRIVE GEOMETRY"); } /* - Initialize the Logical Drive Initial State. + Initialize the Logical Drive Initially Accessible flag. */ for (LogicalDriveNumber = 0; LogicalDriveNumber < Controller->LogicalDriveCount; LogicalDriveNumber++) - Controller->LogicalDriveInitialState[LogicalDriveNumber] = - Controller->LogicalDriveInformation[0] - [LogicalDriveNumber].LogicalDriveState; - Controller->LastRebuildStatus = DAC960_NoRebuildOrCheckInProgress; + if (Controller->V1.LogicalDriveInformation + [LogicalDriveNumber].LogicalDriveState != + DAC960_V1_LogicalDrive_Offline) + Controller->LogicalDriveInitiallyAccessible[LogicalDriveNumber] = true; + Controller->V1.LastRebuildStatus = DAC960_V1_NoRebuildOrCheckInProgress; return true; } /* - DAC960_ReportControllerConfiguration reports the Configuration Information of - Controller. + DAC960_V2_ReadControllerConfiguration reads the Configuration Information + from DAC960 V2 Firmware Controllers and initializes the Controller structure. +*/ + +static boolean DAC960_V2_ReadControllerConfiguration(DAC960_Controller_T + *Controller) +{ + DAC960_V2_ControllerInfo_T *ControllerInfo = + &Controller->V2.ControllerInformation; + unsigned short LogicalDeviceNumber = 0; + int ModelNameLength; + if (!DAC960_V2_ControllerInfo(Controller, DAC960_V2_GetControllerInfo, + ControllerInfo, + sizeof(DAC960_V2_ControllerInfo_T))) + return DAC960_Failure(Controller, "GET CONTROLLER INFO"); + if (!DAC960_V2_GeneralInfo(Controller, DAC960_V2_GetHealthStatus, + Controller->V2.HealthStatusBuffer, + sizeof(DAC960_V2_HealthStatusBuffer_T))) + return DAC960_Failure(Controller, "GET HEALTH STATUS"); + /* + Initialize the Controller Model Name and Full Model Name fields. + */ + ModelNameLength = sizeof(ControllerInfo->ControllerName); + if (ModelNameLength > sizeof(Controller->ModelName)-1) + ModelNameLength = sizeof(Controller->ModelName)-1; + memcpy(Controller->ModelName, ControllerInfo->ControllerName, + ModelNameLength); + ModelNameLength--; + while (Controller->ModelName[ModelNameLength] == ' ' || + Controller->ModelName[ModelNameLength] == '\0') + ModelNameLength--; + Controller->ModelName[++ModelNameLength] = '\0'; + strcpy(Controller->FullModelName, "Mylex "); + strcat(Controller->FullModelName, Controller->ModelName); + /* + Initialize the Controller Firmware Version field. + */ + sprintf(Controller->FirmwareVersion, "%d.%02d-%02d", + ControllerInfo->FirmwareMajorVersion, + ControllerInfo->FirmwareMinorVersion, + ControllerInfo->FirmwareTurnNumber); + if (ControllerInfo->FirmwareMajorVersion == 6 && + ControllerInfo->FirmwareMinorVersion == 0 && + ControllerInfo->FirmwareTurnNumber < 1) + { + DAC960_Info("FIRMWARE VERSION %s DOES NOT PROVIDE THE CONTROLLER\n", + Controller, Controller->FirmwareVersion); + DAC960_Info("STATUS MONITORING FUNCTIONALITY NEEDED BY THIS DRIVER.\n", + Controller); + DAC960_Info("PLEASE UPGRADE TO VERSION 6.00-01 OR ABOVE.\n", + Controller); + } + /* + Initialize the Controller Channels, Targets, and Memory Size. + */ + Controller->Channels = ControllerInfo->NumberOfPhysicalChannelsPresent; + Controller->Targets = + ControllerInfo->MaximumTargetsPerChannel + [ControllerInfo->NumberOfPhysicalChannelsPresent-1]; + Controller->MemorySize = ControllerInfo->MemorySizeMB; + /* + Initialize the Controller Queue Depth, Driver Queue Depth, Logical Drive + Count, Maximum Blocks per Command, Controller Scatter/Gather Limit, and + Driver Scatter/Gather Limit. The Driver Queue Depth must be at most one + less than the Controller Queue Depth to allow for an automatic drive + rebuild operation. + */ + Controller->ControllerQueueDepth = ControllerInfo->MaximumParallelCommands; + Controller->DriverQueueDepth = Controller->ControllerQueueDepth - 1; + if (Controller->DriverQueueDepth > DAC960_MaxDriverQueueDepth) + Controller->DriverQueueDepth = DAC960_MaxDriverQueueDepth; + Controller->LogicalDriveCount = ControllerInfo->LogicalDevicesPresent; + Controller->MaxBlocksPerCommand = + ControllerInfo->MaximumDataTransferSizeInBlocks; + Controller->ControllerScatterGatherLimit = + ControllerInfo->MaximumScatterGatherEntries; + Controller->DriverScatterGatherLimit = + Controller->ControllerScatterGatherLimit; + if (Controller->DriverScatterGatherLimit > DAC960_V2_ScatterGatherLimit) + Controller->DriverScatterGatherLimit = DAC960_V2_ScatterGatherLimit; + /* + Initialize the Logical Device Information. + */ + while (true) + { + DAC960_V2_LogicalDeviceInfo_T *NewLogicalDeviceInfo = + &Controller->V2.NewLogicalDeviceInformation; + DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo; + DAC960_V2_PhysicalDevice_T PhysicalDevice; + if (!DAC960_V2_LogicalDeviceInfo(Controller, + DAC960_V2_GetLogicalDeviceInfoValid, + LogicalDeviceNumber, + NewLogicalDeviceInfo, + sizeof(DAC960_V2_LogicalDeviceInfo_T))) + break; + LogicalDeviceNumber = NewLogicalDeviceInfo->LogicalDeviceNumber; + if (LogicalDeviceNumber > DAC960_MaxLogicalDrives) + panic("DAC960: Logical Drive Number %d not supported\n", + LogicalDeviceNumber); + if (NewLogicalDeviceInfo->DeviceBlockSizeInBytes != DAC960_BlockSize) + panic("DAC960: Logical Drive Block Size %d not supported\n", + NewLogicalDeviceInfo->DeviceBlockSizeInBytes); + PhysicalDevice.Controller = 0; + PhysicalDevice.Channel = NewLogicalDeviceInfo->Channel; + PhysicalDevice.TargetID = NewLogicalDeviceInfo->TargetID; + PhysicalDevice.LogicalUnit = NewLogicalDeviceInfo->LogicalUnit; + Controller->V2.LogicalDriveToVirtualDevice[LogicalDeviceNumber] = + PhysicalDevice; + if (NewLogicalDeviceInfo->LogicalDeviceState != + DAC960_V2_LogicalDevice_Offline) + Controller->LogicalDriveInitiallyAccessible[LogicalDeviceNumber] = true; + LogicalDeviceInfo = (DAC960_V2_LogicalDeviceInfo_T *) + kmalloc(sizeof(DAC960_V2_LogicalDeviceInfo_T), GFP_ATOMIC); + if (LogicalDeviceInfo == NULL) + return DAC960_Failure(Controller, "LOGICAL DEVICE ALLOCATION"); + Controller->V2.LogicalDeviceInformation[LogicalDeviceNumber] = + LogicalDeviceInfo; + memcpy(LogicalDeviceInfo, NewLogicalDeviceInfo, + sizeof(DAC960_V2_LogicalDeviceInfo_T)); + LogicalDeviceNumber++; + } + return true; +} + + +/* + DAC960_ReportControllerConfiguration reports the Configuration Information + for Controller. */ static boolean DAC960_ReportControllerConfiguration(DAC960_Controller_T @@ -893,54 +1291,60 @@ Controller, Controller->ControllerQueueDepth, Controller->MaxBlocksPerCommand); DAC960_Info(" Driver Queue Depth: %d, " - "Maximum Scatter/Gather Segments: %d\n", + "Scatter/Gather Limit: %d of %d Segments\n", Controller, Controller->DriverQueueDepth, - Controller->MaxScatterGatherSegments); - DAC960_Info(" Stripe Size: %dKB, Segment Size: %dKB, " - "BIOS Geometry: %d/%d\n", Controller, - Controller->StripeSize, - Controller->SegmentSize, - Controller->GeometryTranslationHeads, - Controller->GeometryTranslationSectors); - if (Controller->SAFTE_EnclosureManagementEnabled) - DAC960_Info(" SAF-TE Enclosure Management Enabled\n", Controller); + Controller->DriverScatterGatherLimit, + Controller->ControllerScatterGatherLimit); + if (Controller->FirmwareType == DAC960_V1_Controller) + { + DAC960_Info(" Stripe Size: %dKB, Segment Size: %dKB, " + "BIOS Geometry: %d/%d\n", Controller, + Controller->V1.StripeSize, + Controller->V1.SegmentSize, + Controller->V1.GeometryTranslationHeads, + Controller->V1.GeometryTranslationSectors); + if (Controller->V1.SAFTE_EnclosureManagementEnabled) + DAC960_Info(" SAF-TE Enclosure Management Enabled\n", Controller); + } return true; } /* - DAC960_ReadDeviceConfiguration reads the Device Configuration Information by - requesting the SCSI Inquiry and SCSI Inquiry Unit Serial Number information - for each device connected to Controller. + DAC960_V1_ReadDeviceConfiguration reads the Device Configuration Information + for DAC960 V1 Firmware Controllers by requesting the SCSI Inquiry and SCSI + Inquiry Unit Serial Number information for each device connected to + Controller. */ -static boolean DAC960_ReadDeviceConfiguration(DAC960_Controller_T *Controller) +static boolean DAC960_V1_ReadDeviceConfiguration(DAC960_Controller_T + *Controller) { - DAC960_DCDB_T DCDBs[DAC960_MaxChannels], *DCDB; - Semaphore_T Semaphores[DAC960_MaxChannels], *Semaphore; + DAC960_V1_DCDB_T DCDBs[DAC960_V1_MaxChannels], *DCDB; + Semaphore_T Semaphores[DAC960_V1_MaxChannels], *Semaphore; unsigned long ProcessorFlags; int Channel, TargetID; - for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++) + for (TargetID = 0; TargetID < Controller->Targets; TargetID++) { for (Channel = 0; Channel < Controller->Channels; Channel++) { - DAC960_Command_T *Command = &Controller->Commands[Channel]; + DAC960_Command_T *Command = Controller->Commands[Channel]; DAC960_SCSI_Inquiry_T *InquiryStandardData = - &Controller->InquiryStandardData[Channel][TargetID]; + &Controller->V1.InquiryStandardData[Channel][TargetID]; InquiryStandardData->PeripheralDeviceType = 0x1F; Semaphore = &Semaphores[Channel]; init_MUTEX_LOCKED(Semaphore); DCDB = &DCDBs[Channel]; - DAC960_ClearCommand(Command); + DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; Command->Semaphore = Semaphore; - Command->CommandMailbox.Type3.CommandOpcode = DAC960_DCDB; - Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB); + Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB; + Command->V1.CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB); DCDB->Channel = Channel; DCDB->TargetID = TargetID; - DCDB->Direction = DAC960_DCDB_DataTransferDeviceToSystem; + DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem; DCDB->EarlyStatus = false; - DCDB->Timeout = DAC960_DCDB_Timeout_10_seconds; + DCDB->Timeout = DAC960_V1_DCDB_Timeout_10_seconds; DCDB->NoAutomaticRequestSense = false; DCDB->DisconnectPermitted = true; DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_T); @@ -960,13 +1364,14 @@ } for (Channel = 0; Channel < Controller->Channels; Channel++) { - DAC960_Command_T *Command = &Controller->Commands[Channel]; + DAC960_Command_T *Command = Controller->Commands[Channel]; DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber = - &Controller->InquiryUnitSerialNumber[Channel][TargetID]; + &Controller->V1.InquiryUnitSerialNumber[Channel][TargetID]; InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; Semaphore = &Semaphores[Channel]; down(Semaphore); - if (Command->CommandStatus != DAC960_NormalCompletion) continue; + if (Command->V1.CommandStatus != DAC960_V1_NormalCompletion) + continue; Command->Semaphore = Semaphore; DCDB = &DCDBs[Channel]; DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); @@ -984,107 +1389,215 @@ down(Semaphore); } } - return true; + return true; +} + + +/* + DAC960_V2_ReadDeviceConfiguration reads the Device Configuration Information + for DAC960 V2 Firmware Controllers by requesting the Physical Device + Information and SCSI Inquiry Unit Serial Number information for each + device connected to Controller. +*/ + +static boolean DAC960_V2_ReadDeviceConfiguration(DAC960_Controller_T + *Controller) +{ + unsigned char Channel = 0, TargetID = 0, LogicalUnit = 0; + unsigned short PhysicalDeviceIndex = 0; + while (true) + { + DAC960_V2_PhysicalDeviceInfo_T *NewPhysicalDeviceInfo = + &Controller->V2.NewPhysicalDeviceInformation; + DAC960_V2_PhysicalDeviceInfo_T *PhysicalDeviceInfo; + DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber; + DAC960_Command_T *Command; + DAC960_V2_CommandMailbox_T *CommandMailbox; + if (!DAC960_V2_PhysicalDeviceInfo(Controller, + DAC960_V2_GetPhysicalDeviceInfoValid, + Channel, + TargetID, + LogicalUnit, + NewPhysicalDeviceInfo, + sizeof(DAC960_V2_PhysicalDeviceInfo_T))) + break; + Channel = NewPhysicalDeviceInfo->Channel; + TargetID = NewPhysicalDeviceInfo->TargetID; + LogicalUnit = NewPhysicalDeviceInfo->LogicalUnit; + PhysicalDeviceInfo = (DAC960_V2_PhysicalDeviceInfo_T *) + kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T), GFP_ATOMIC); + if (PhysicalDeviceInfo == NULL) + return DAC960_Failure(Controller, "PHYSICAL DEVICE ALLOCATION"); + Controller->V2.PhysicalDeviceInformation[PhysicalDeviceIndex] = + PhysicalDeviceInfo; + memcpy(PhysicalDeviceInfo, NewPhysicalDeviceInfo, + sizeof(DAC960_V2_PhysicalDeviceInfo_T)); + InquiryUnitSerialNumber = (DAC960_SCSI_Inquiry_UnitSerialNumber_T *) + kmalloc(sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), GFP_ATOMIC); + if (InquiryUnitSerialNumber == NULL) + return DAC960_Failure(Controller, "SERIAL NUMBER ALLOCATION"); + Controller->V2.InquiryUnitSerialNumber[PhysicalDeviceIndex] = + InquiryUnitSerialNumber; + memset(InquiryUnitSerialNumber, 0, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)); + InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; + Command = DAC960_AllocateCommand(Controller); + CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_ClearCommand(Command); + Command->CommandType = DAC960_ImmediateCommand; + CommandMailbox->SCSI_10.CommandOpcode = DAC960_V2_SCSI_10_Passthru; + CommandMailbox->SCSI_10.CommandControlBits + .DataTransferControllerToHost = true; + CommandMailbox->SCSI_10.CommandControlBits + .NoAutoRequestSense = true; + CommandMailbox->SCSI_10.DataTransferSize = + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); + CommandMailbox->SCSI_10.PhysicalDevice.LogicalUnit = LogicalUnit; + CommandMailbox->SCSI_10.PhysicalDevice.TargetID = TargetID; + CommandMailbox->SCSI_10.PhysicalDevice.Channel = Channel; + CommandMailbox->SCSI_10.CDBLength = 6; + CommandMailbox->SCSI_10.SCSI_CDB[0] = 0x12; /* INQUIRY */ + CommandMailbox->SCSI_10.SCSI_CDB[1] = 1; /* EVPD = 1 */ + CommandMailbox->SCSI_10.SCSI_CDB[2] = 0x80; /* Page Code */ + CommandMailbox->SCSI_10.SCSI_CDB[3] = 0; /* Reserved */ + CommandMailbox->SCSI_10.SCSI_CDB[4] = + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); + CommandMailbox->SCSI_10.SCSI_CDB[5] = 0; /* Control */ + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(InquiryUnitSerialNumber); + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->SCSI_10.DataTransferSize; + DAC960_ExecuteCommand(Command); + DAC960_DeallocateCommand(Command); + PhysicalDeviceIndex++; + LogicalUnit++; + } + return true; } /* - DAC960_ReportDeviceConfiguration reports the Device Configuration Information - of Controller. + DAC960_SanitizeInquiryData sanitizes the Vendor, Model, Revision, and + Product Serial Number fields of the Inquiry Standard Data and Inquiry + Unit Serial Number structures. */ -static boolean DAC960_ReportDeviceConfiguration(DAC960_Controller_T *Controller) +static void DAC960_SanitizeInquiryData(DAC960_SCSI_Inquiry_T + *InquiryStandardData, + DAC960_SCSI_Inquiry_UnitSerialNumber_T + *InquiryUnitSerialNumber, + unsigned char *Vendor, + unsigned char *Model, + unsigned char *Revision, + unsigned char *SerialNumber) +{ + int SerialNumberLength, i; + if (InquiryStandardData->PeripheralDeviceType == 0x1F) return; + for (i = 0; i < sizeof(InquiryStandardData->VendorIdentification); i++) + { + unsigned char VendorCharacter = + InquiryStandardData->VendorIdentification[i]; + Vendor[i] = (VendorCharacter >= ' ' && VendorCharacter <= '~' + ? VendorCharacter : ' '); + } + Vendor[sizeof(InquiryStandardData->VendorIdentification)] = '\0'; + for (i = 0; i < sizeof(InquiryStandardData->ProductIdentification); i++) + { + unsigned char ModelCharacter = + InquiryStandardData->ProductIdentification[i]; + Model[i] = (ModelCharacter >= ' ' && ModelCharacter <= '~' + ? ModelCharacter : ' '); + } + Model[sizeof(InquiryStandardData->ProductIdentification)] = '\0'; + for (i = 0; i < sizeof(InquiryStandardData->ProductRevisionLevel); i++) + { + unsigned char RevisionCharacter = + InquiryStandardData->ProductRevisionLevel[i]; + Revision[i] = (RevisionCharacter >= ' ' && RevisionCharacter <= '~' + ? RevisionCharacter : ' '); + } + Revision[sizeof(InquiryStandardData->ProductRevisionLevel)] = '\0'; + if (InquiryUnitSerialNumber->PeripheralDeviceType == 0x1F) return; + SerialNumberLength = InquiryUnitSerialNumber->PageLength; + if (SerialNumberLength > + sizeof(InquiryUnitSerialNumber->ProductSerialNumber)) + SerialNumberLength = sizeof(InquiryUnitSerialNumber->ProductSerialNumber); + for (i = 0; i < SerialNumberLength; i++) + { + unsigned char SerialNumberCharacter = + InquiryUnitSerialNumber->ProductSerialNumber[i]; + SerialNumber[i] = + (SerialNumberCharacter >= ' ' && SerialNumberCharacter <= '~' + ? SerialNumberCharacter : ' '); + } + SerialNumber[SerialNumberLength] = '\0'; +} + + +/* + DAC960_V1_ReportDeviceConfiguration reports the Device Configuration + Information for DAC960 V1 Firmware Controllers. +*/ + +static boolean DAC960_V1_ReportDeviceConfiguration(DAC960_Controller_T + *Controller) { int LogicalDriveNumber, Channel, TargetID; DAC960_Info(" Physical Devices:\n", Controller); for (Channel = 0; Channel < Controller->Channels; Channel++) - for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++) + for (TargetID = 0; TargetID < Controller->Targets; TargetID++) { DAC960_SCSI_Inquiry_T *InquiryStandardData = - &Controller->InquiryStandardData[Channel][TargetID]; + &Controller->V1.InquiryStandardData[Channel][TargetID]; DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber = - &Controller->InquiryUnitSerialNumber[Channel][TargetID]; - DAC960_DeviceState_T *DeviceState = - &Controller->DeviceState[Controller->DeviceStateIndex] - [Channel][TargetID]; - DAC960_ErrorTable_T *ErrorTable = - &Controller->ErrorTable[Controller->ErrorTableIndex]; - DAC960_ErrorTableEntry_T *ErrorEntry = - &ErrorTable->ErrorTableEntries[Channel][TargetID]; + &Controller->V1.InquiryUnitSerialNumber[Channel][TargetID]; + DAC960_V1_DeviceState_T *DeviceState = + &Controller->V1.DeviceState[Channel][TargetID]; + DAC960_V1_ErrorTableEntry_T *ErrorEntry = + &Controller->V1.ErrorTable.ErrorTableEntries[Channel][TargetID]; char Vendor[1+sizeof(InquiryStandardData->VendorIdentification)]; char Model[1+sizeof(InquiryStandardData->ProductIdentification)]; char Revision[1+sizeof(InquiryStandardData->ProductRevisionLevel)]; char SerialNumber[1+sizeof(InquiryUnitSerialNumber ->ProductSerialNumber)]; - int i; if (InquiryStandardData->PeripheralDeviceType == 0x1F) continue; - for (i = 0; i < sizeof(Vendor)-1; i++) - { - unsigned char VendorCharacter = - InquiryStandardData->VendorIdentification[i]; - Vendor[i] = (VendorCharacter >= ' ' && VendorCharacter <= '~' - ? VendorCharacter : ' '); - } - Vendor[sizeof(Vendor)-1] = '\0'; - for (i = 0; i < sizeof(Model)-1; i++) - { - unsigned char ModelCharacter = - InquiryStandardData->ProductIdentification[i]; - Model[i] = (ModelCharacter >= ' ' && ModelCharacter <= '~' - ? ModelCharacter : ' '); - } - Model[sizeof(Model)-1] = '\0'; - for (i = 0; i < sizeof(Revision)-1; i++) - { - unsigned char RevisionCharacter = - InquiryStandardData->ProductRevisionLevel[i]; - Revision[i] = (RevisionCharacter >= ' ' && RevisionCharacter <= '~' - ? RevisionCharacter : ' '); - } - Revision[sizeof(Revision)-1] = '\0'; + DAC960_SanitizeInquiryData(InquiryStandardData, InquiryUnitSerialNumber, + Vendor, Model, Revision, SerialNumber); DAC960_Info(" %d:%d%s Vendor: %s Model: %s Revision: %s\n", Controller, Channel, TargetID, (TargetID < 10 ? " " : ""), Vendor, Model, Revision); if (InquiryUnitSerialNumber->PeripheralDeviceType != 0x1F) + DAC960_Info(" Serial Number: %s\n", Controller, SerialNumber); + if (DeviceState->Present && + DeviceState->DeviceType == DAC960_V1_DiskType) { - int SerialNumberLength = InquiryUnitSerialNumber->PageLength; - if (SerialNumberLength > - sizeof(InquiryUnitSerialNumber->ProductSerialNumber)) - SerialNumberLength = - sizeof(InquiryUnitSerialNumber->ProductSerialNumber); - for (i = 0; i < SerialNumberLength; i++) - { - unsigned char SerialNumberCharacter = - InquiryUnitSerialNumber->ProductSerialNumber[i]; - SerialNumber[i] = - (SerialNumberCharacter >= ' ' && SerialNumberCharacter <= '~' - ? SerialNumberCharacter : ' '); - } - SerialNumber[SerialNumberLength] = '\0'; - DAC960_Info(" Serial Number: %s\n", - Controller, SerialNumber); - } - if (DeviceState->Present && DeviceState->DeviceType == DAC960_DiskType) - { - if (Controller->DeviceResetCount[Channel][TargetID] > 0) + if (Controller->V1.DeviceResetCount[Channel][TargetID] > 0) DAC960_Info(" Disk Status: %s, %d blocks, %d resets\n", Controller, - (DeviceState->DeviceState == DAC960_Device_Dead + (DeviceState->DeviceState == DAC960_V1_Device_Dead ? "Dead" - : DeviceState->DeviceState == DAC960_Device_WriteOnly - ? "Write-Only" - : DeviceState->DeviceState == DAC960_Device_Online - ? "Online" : "Standby"), + : DeviceState->DeviceState + == DAC960_V1_Device_WriteOnly + ? "Write-Only" + : DeviceState->DeviceState + == DAC960_V1_Device_Online + ? "Online" : "Standby"), DeviceState->DiskSize, - Controller->DeviceResetCount[Channel][TargetID]); + Controller->V1.DeviceResetCount[Channel][TargetID]); else DAC960_Info(" Disk Status: %s, %d blocks\n", Controller, - (DeviceState->DeviceState == DAC960_Device_Dead + (DeviceState->DeviceState == DAC960_V1_Device_Dead ? "Dead" - : DeviceState->DeviceState == DAC960_Device_WriteOnly - ? "Write-Only" - : DeviceState->DeviceState == DAC960_Device_Online - ? "Online" : "Standby"), + : DeviceState->DeviceState + == DAC960_V1_Device_WriteOnly + ? "Write-Only" + : DeviceState->DeviceState + == DAC960_V1_Device_Online + ? "Online" : "Standby"), DeviceState->DiskSize); } if (ErrorEntry->ParityErrorCount > 0 || @@ -1103,17 +1616,16 @@ LogicalDriveNumber < Controller->LogicalDriveCount; LogicalDriveNumber++) { - DAC960_LogicalDriveInformation_T *LogicalDriveInformation = - &Controller->LogicalDriveInformation - [Controller->LogicalDriveInformationIndex][LogicalDriveNumber]; + DAC960_V1_LogicalDriveInformation_T *LogicalDriveInformation = + &Controller->V1.LogicalDriveInformation[LogicalDriveNumber]; DAC960_Info(" /dev/rd/c%dd%d: RAID-%d, %s, %d blocks, %s\n", Controller, Controller->ControllerNumber, LogicalDriveNumber, LogicalDriveInformation->RAIDLevel, - (LogicalDriveInformation->LogicalDriveState == - DAC960_LogicalDrive_Online + (LogicalDriveInformation->LogicalDriveState + == DAC960_V1_LogicalDrive_Online ? "Online" - : LogicalDriveInformation->LogicalDriveState == - DAC960_LogicalDrive_Critical + : LogicalDriveInformation->LogicalDriveState + == DAC960_V1_LogicalDrive_Critical ? "Critical" : "Offline"), LogicalDriveInformation->LogicalDriveSize, (LogicalDriveInformation->WriteBack @@ -1123,69 +1635,256 @@ } -static inline int DAC_new_segment(request_queue_t *q, struct request *req, - int __max_segments) -{ - int max_segments; - DAC960_Controller_T * Controller = q->queuedata; +/* + DAC960_V2_ReportDeviceConfiguration reports the Device Configuration + Information for DAC960 V2 Firmware Controllers. +*/ - max_segments = Controller->MaxSegmentsPerRequest[MINOR(req->rq_dev)]; - if (__max_segments < max_segments) - max_segments = __max_segments; - - if (req->nr_segments < max_segments) { - req->nr_segments++; - q->elevator.nr_segments++; - return 1; +static boolean DAC960_V2_ReportDeviceConfiguration(DAC960_Controller_T + *Controller) +{ + int PhysicalDeviceIndex, LogicalDriveNumber; + DAC960_Info(" Physical Devices:\n", Controller); + for (PhysicalDeviceIndex = 0; + PhysicalDeviceIndex < DAC960_V2_MaxPhysicalDevices; + PhysicalDeviceIndex++) + { + DAC960_V2_PhysicalDeviceInfo_T *PhysicalDeviceInfo = + Controller->V2.PhysicalDeviceInformation[PhysicalDeviceIndex]; + DAC960_SCSI_Inquiry_T *InquiryStandardData = + (DAC960_SCSI_Inquiry_T *) &PhysicalDeviceInfo->SCSI_InquiryData; + DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber = + Controller->V2.InquiryUnitSerialNumber[PhysicalDeviceIndex]; + char Vendor[1+sizeof(InquiryStandardData->VendorIdentification)]; + char Model[1+sizeof(InquiryStandardData->ProductIdentification)]; + char Revision[1+sizeof(InquiryStandardData->ProductRevisionLevel)]; + char SerialNumber[1+sizeof(InquiryUnitSerialNumber->ProductSerialNumber)]; + if (PhysicalDeviceInfo == NULL) break; + DAC960_SanitizeInquiryData(InquiryStandardData, InquiryUnitSerialNumber, + Vendor, Model, Revision, SerialNumber); + DAC960_Info(" %d:%d%s Vendor: %s Model: %s Revision: %s\n", + Controller, + PhysicalDeviceInfo->Channel, + PhysicalDeviceInfo->TargetID, + (PhysicalDeviceInfo->TargetID < 10 ? " " : ""), + Vendor, Model, Revision); + if (PhysicalDeviceInfo->NegotiatedSynchronousMegaTransfers == 0) + DAC960_Info(" %sAsynchronous\n", Controller, + (PhysicalDeviceInfo->NegotiatedDataWidthBits == 16 + ? "Wide " :"")); + else + DAC960_Info(" %sSynchronous at %d MB/sec\n", Controller, + (PhysicalDeviceInfo->NegotiatedDataWidthBits == 16 + ? "Wide " :""), + (PhysicalDeviceInfo->NegotiatedSynchronousMegaTransfers + * (PhysicalDeviceInfo->NegotiatedDataWidthBits == 16 + ? 2 : 1))); + if (InquiryUnitSerialNumber->PeripheralDeviceType != 0x1F) + DAC960_Info(" Serial Number: %s\n", Controller, SerialNumber); + if (PhysicalDeviceInfo->PhysicalDeviceState == + DAC960_V2_Device_Unconfigured) + continue; + DAC960_Info(" Disk Status: %s, %d blocks\n", Controller, + (PhysicalDeviceInfo->PhysicalDeviceState + == DAC960_V2_Device_Online + ? "Online" + : PhysicalDeviceInfo->PhysicalDeviceState + == DAC960_V2_Device_WriteOnly + ? "Write-Only" + : PhysicalDeviceInfo->PhysicalDeviceState + == DAC960_V2_Device_Dead + ? "Dead" : "Standby"), + PhysicalDeviceInfo + ->ConfigurableDeviceSizeIn512ByteBlocksOrMB); + if (PhysicalDeviceInfo->ParityErrors == 0 && + PhysicalDeviceInfo->SoftErrors == 0 && + PhysicalDeviceInfo->HardErrors == 0 && + PhysicalDeviceInfo->MiscellaneousErrors == 0 && + PhysicalDeviceInfo->CommandTimeouts == 0 && + PhysicalDeviceInfo->Retries == 0 && + PhysicalDeviceInfo->Aborts == 0 && + PhysicalDeviceInfo->PredictedFailuresDetected == 0) + continue; + DAC960_Info(" Errors - Parity: %d, Soft: %d, " + "Hard: %d, Misc: %d\n", Controller, + PhysicalDeviceInfo->ParityErrors, + PhysicalDeviceInfo->SoftErrors, + PhysicalDeviceInfo->HardErrors, + PhysicalDeviceInfo->MiscellaneousErrors); + DAC960_Info(" Timeouts: %d, Retries: %d, " + "Aborts: %d, Predicted: %d\n", Controller, + PhysicalDeviceInfo->CommandTimeouts, + PhysicalDeviceInfo->Retries, + PhysicalDeviceInfo->Aborts, + PhysicalDeviceInfo->PredictedFailuresDetected); + } + DAC960_Info(" Logical Drives:\n", Controller); + for (LogicalDriveNumber = 0; + LogicalDriveNumber < DAC960_MaxLogicalDrives; + LogicalDriveNumber++) + { + DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo = + Controller->V2.LogicalDeviceInformation[LogicalDriveNumber]; + unsigned char *ReadCacheStatus[] = { "Read Cache Disabled", + "Read Cache Enabled", + "Read Ahead Enabled", + "Intelligent Read Ahead Enabled", + "-", "-", "-", "-" }; + unsigned char *WriteCacheStatus[] = { "Write Cache Disabled", + "Logical Device Read Only", + "Write Cache Enabled", + "Intelligent Write Cache Enabled", + "-", "-", "-", "-" }; + unsigned char *GeometryTranslation; + if (LogicalDeviceInfo == NULL) continue; + switch(LogicalDeviceInfo->DriveGeometry) + { + case DAC960_V2_Geometry_128_32: + GeometryTranslation = "128/32"; + break; + case DAC960_V2_Geometry_255_63: + GeometryTranslation = "255/63"; + break; + default: + GeometryTranslation = "Invalid"; + DAC960_Error("Illegal Logical Device Geometry %d\n", + Controller, LogicalDeviceInfo->DriveGeometry); + break; } - return 0; -} + DAC960_Info(" /dev/rd/c%dd%d: RAID-%d, %s, %d blocks\n", + Controller, Controller->ControllerNumber, LogicalDriveNumber, + LogicalDeviceInfo->RAIDLevel, + (LogicalDeviceInfo->LogicalDeviceState + == DAC960_V2_LogicalDevice_Online + ? "Online" + : LogicalDeviceInfo->LogicalDeviceState + == DAC960_V2_LogicalDevice_Critical + ? "Critical" : "Offline"), + LogicalDeviceInfo->ConfigurableDeviceSizeIn512ByteBlocksOrMB); + DAC960_Info(" Logical Device %s, BIOS Geometry: %s\n", + Controller, + (LogicalDeviceInfo->LogicalDeviceControl + .LogicalDeviceInitialized + ? "Initialized" : "Uninitialized"), + GeometryTranslation); + if (LogicalDeviceInfo->StripeSize == 0) + { + if (LogicalDeviceInfo->CacheLineSize == 0) + DAC960_Info(" Stripe Size: N/A, " + "Segment Size: N/A\n", Controller); + else + DAC960_Info(" Stripe Size: N/A, " + "Segment Size: %dKB\n", Controller, + 1 << (LogicalDeviceInfo->CacheLineSize - 2)); + } + else + { + if (LogicalDeviceInfo->CacheLineSize == 0) + DAC960_Info(" Stripe Size: %dKB, " + "Segment Size: N/A\n", Controller, + 1 << (LogicalDeviceInfo->StripeSize - 2)); + else + DAC960_Info(" Stripe Size: %dKB, " + "Segment Size: %dKB\n", Controller, + 1 << (LogicalDeviceInfo->StripeSize - 2), + 1 << (LogicalDeviceInfo->CacheLineSize - 2)); + } + DAC960_Info(" %s, %s\n", Controller, + ReadCacheStatus[ + LogicalDeviceInfo->LogicalDeviceControl.ReadCache], + WriteCacheStatus[ + LogicalDeviceInfo->LogicalDeviceControl.WriteCache]); + if (LogicalDeviceInfo->SoftErrors > 0 || + LogicalDeviceInfo->CommandsFailed > 0 || + LogicalDeviceInfo->DeferredWriteErrors) + DAC960_Info(" Errors - Soft: %d, Failed: %d, " + "Deferred Write: %d\n", Controller, + LogicalDeviceInfo->SoftErrors, + LogicalDeviceInfo->CommandsFailed, + LogicalDeviceInfo->DeferredWriteErrors); -static int DAC_back_merge_fn(request_queue_t *q, struct request *req, - struct buffer_head *bh, int __max_segments) -{ - if (req->bhtail->b_data + req->bhtail->b_size == bh->b_data) - return 1; - return DAC_new_segment(q, req, __max_segments); + } + return true; } -static int DAC_front_merge_fn(request_queue_t *q, struct request *req, - struct buffer_head *bh, int __max_segments) + +/* + DAC960_BackMergeFunction is the Back Merge Function for the DAC960 driver. +*/ + +static int DAC960_BackMergeFunction(RequestQueue_T *RequestQueue, + IO_Request_T *Request, + BufferHeader_T *BufferHeader, + int MaxSegments) { - if (bh->b_data + bh->b_size == req->bh->b_data) - return 1; - return DAC_new_segment(q, req, __max_segments); + DAC960_Controller_T *Controller = + (DAC960_Controller_T *) RequestQueue->queuedata; + if (Request->bhtail->b_data + Request->bhtail->b_size == BufferHeader->b_data) + return true; + if (Request->nr_segments < MaxSegments && + Request->nr_segments < Controller->DriverScatterGatherLimit) + { + Request->nr_segments++; + RequestQueue->elevator.nr_segments++; + return true; + } + return false; } -static int DAC_merge_requests_fn(request_queue_t *q, - struct request *req, - struct request *next, - int __max_segments) + +/* + DAC960_FrontMergeFunction is the Front Merge Function for the DAC960 driver. +*/ + +static int DAC960_FrontMergeFunction(RequestQueue_T *RequestQueue, + IO_Request_T *Request, + BufferHeader_T *BufferHeader, + int MaxSegments) { - int max_segments; - DAC960_Controller_T * Controller = q->queuedata; - int total_segments = req->nr_segments + next->nr_segments; - int same_segment; + DAC960_Controller_T *Controller = + (DAC960_Controller_T *) RequestQueue->queuedata; + if (BufferHeader->b_data + BufferHeader->b_size == Request->bh->b_data) + return true; + if (Request->nr_segments < MaxSegments && + Request->nr_segments < Controller->DriverScatterGatherLimit) + { + Request->nr_segments++; + RequestQueue->elevator.nr_segments++; + return true; + } + return false; +} - max_segments = Controller->MaxSegmentsPerRequest[MINOR(req->rq_dev)]; - if (__max_segments < max_segments) - max_segments = __max_segments; - same_segment = 0; - if (req->bhtail->b_data + req->bhtail->b_size == next->bh->b_data) - { - total_segments--; - same_segment = 1; - } - - if (total_segments > max_segments) - return 0; +/* + DAC960_MergeRequestsFunction is the Merge Requests Function for the + DAC960 driver. +*/ - q->elevator.nr_segments -= same_segment; - req->nr_segments = total_segments; - return 1; +static int DAC960_MergeRequestsFunction(RequestQueue_T *RequestQueue, + IO_Request_T *Request, + IO_Request_T *NextRequest, + int MaxSegments) +{ + DAC960_Controller_T *Controller = + (DAC960_Controller_T *) RequestQueue->queuedata; + int TotalSegments = Request->nr_segments + NextRequest->nr_segments; + int SameSegment = 0; + if (Request->bhtail->b_data + Request->bhtail->b_size + == NextRequest->bh->b_data) + { + TotalSegments--; + SameSegment = 1; + } + if (TotalSegments > MaxSegments || + TotalSegments > Controller->DriverScatterGatherLimit) + return false; + RequestQueue->elevator.nr_segments -= SameSegment; + Request->nr_segments = TotalSegments; + return true; } + /* DAC960_RegisterBlockDevice registers the Block Device structures associated with Controller. @@ -1193,47 +1892,40 @@ static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller) { - request_queue_t * q; - - static void (*RequestFunctions[DAC960_MaxControllers])(request_queue_t *) = - { DAC960_RequestFunction0, DAC960_RequestFunction1, - DAC960_RequestFunction2, DAC960_RequestFunction3, - DAC960_RequestFunction4, DAC960_RequestFunction5, - DAC960_RequestFunction6, DAC960_RequestFunction7 }; int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber; GenericDiskInfo_T *GenericDiskInfo; + RequestQueue_T *RequestQueue; int MinorNumber; /* Register the Block Device Major Number for this DAC960 Controller. */ - if (devfs_register_blkdev(MajorNumber, "dac960", &DAC960_FileOperations) < 0) + if (devfs_register_blkdev(MajorNumber, "dac960", + &DAC960_BlockDeviceOperations) < 0) { DAC960_Error("UNABLE TO ACQUIRE MAJOR NUMBER %d - DETACHING\n", Controller, MajorNumber); return false; } /* - Initialize the I/O Request Function. + Initialize the I/O Request Queue. */ - q = BLK_DEFAULT_QUEUE(MajorNumber); - blk_init_queue(q, RequestFunctions[Controller->ControllerNumber]); - blk_queue_headactive(q, 0); - q->back_merge_fn = DAC_back_merge_fn; - q->front_merge_fn = DAC_front_merge_fn; - q->merge_requests_fn = DAC_merge_requests_fn; - q->queuedata = (void *) Controller; - + RequestQueue = BLK_DEFAULT_QUEUE(MajorNumber); + blk_init_queue(RequestQueue, DAC960_RequestFunction); + blk_queue_headactive(RequestQueue, 0); + RequestQueue->back_merge_fn = DAC960_BackMergeFunction; + RequestQueue->front_merge_fn = DAC960_FrontMergeFunction; + RequestQueue->merge_requests_fn = DAC960_MergeRequestsFunction; + RequestQueue->queuedata = Controller; + Controller->RequestQueue = RequestQueue; /* Initialize the Disk Partitions array, Partition Sizes array, Block Sizes - array, Max Sectors per Request array, and Max Segments per Request array. + array, and Max Sectors per Request array. */ for (MinorNumber = 0; MinorNumber < DAC960_MinorCount; MinorNumber++) { Controller->BlockSizes[MinorNumber] = BLOCK_SIZE; Controller->MaxSectorsPerRequest[MinorNumber] = Controller->MaxBlocksPerCommand; - Controller->MaxSegmentsPerRequest[MinorNumber] = - Controller->MaxScatterGatherSegments; } Controller->GenericDiskInfo.part = Controller->DiskPartitions; Controller->GenericDiskInfo.sizes = Controller->PartitionSizes; @@ -1247,13 +1939,12 @@ Complete initialization of the Generic Disk Information structure. */ Controller->GenericDiskInfo.major = MajorNumber; - Controller->GenericDiskInfo.major_name = "dac960"; + Controller->GenericDiskInfo.major_name = "rd"; Controller->GenericDiskInfo.minor_shift = DAC960_MaxPartitionsBits; Controller->GenericDiskInfo.max_p = DAC960_MaxPartitions; Controller->GenericDiskInfo.nr_real = Controller->LogicalDriveCount; - Controller->GenericDiskInfo.real_devices = Controller; Controller->GenericDiskInfo.next = NULL; - Controller->GenericDiskInfo.fops = &DAC960_FileOperations; + Controller->GenericDiskInfo.fops = &DAC960_BlockDeviceOperations; /* Install the Generic Disk Information structure at the end of the list. */ @@ -1284,7 +1975,7 @@ */ devfs_unregister_blkdev(MajorNumber, "dac960"); /* - Remove the I/O Request Function. + Remove the I/O Request Queue. */ blk_cleanup_queue(BLK_DEFAULT_QUEUE(MajorNumber)); /* @@ -1313,78 +2004,539 @@ /* - DAC960_InitializeController initializes Controller. + DAC960_RegisterDisk registers the DAC960 Logical Disk Device for Logical + Drive Number if it exists. */ -static void DAC960_InitializeController(DAC960_Controller_T *Controller) +static void DAC960_RegisterDisk(DAC960_Controller_T *Controller, + int LogicalDriveNumber) { - if (DAC960_ReadControllerConfiguration(Controller) && - DAC960_ReportControllerConfiguration(Controller) && - DAC960_ReadDeviceConfiguration(Controller) && - DAC960_ReportDeviceConfiguration(Controller) && - DAC960_RegisterBlockDevice(Controller)) + if (Controller->FirmwareType == DAC960_V1_Controller) { - /* - Initialize the Command structures. - */ - DAC960_Command_T *Commands = Controller->Commands; - int CommandIdentifier; - Controller->FreeCommands = NULL; - for (CommandIdentifier = 0; - CommandIdentifier < Controller->DriverQueueDepth; - CommandIdentifier++) - { - Commands[CommandIdentifier].Controller = Controller; - Commands[CommandIdentifier].Next = Controller->FreeCommands; - Controller->FreeCommands = &Commands[CommandIdentifier]; - } - /* - Initialize the Monitoring Timer. - */ - init_timer(&Controller->MonitoringTimer); - Controller->MonitoringTimer.expires = - jiffies + DAC960_MonitoringTimerInterval; - Controller->MonitoringTimer.data = (unsigned long) Controller; - Controller->MonitoringTimer.function = DAC960_MonitoringTimerFunction; - add_timer(&Controller->MonitoringTimer); - Controller->ControllerInitialized = true; - DAC960_InitializeGenericDiskInfo(&Controller->GenericDiskInfo); + if (LogicalDriveNumber > Controller->LogicalDriveCount - 1) return; + register_disk(&Controller->GenericDiskInfo, + DAC960_KernelDevice(Controller->ControllerNumber, + LogicalDriveNumber, 0), + DAC960_MaxPartitions, &DAC960_BlockDeviceOperations, + Controller->V1.LogicalDriveInformation + [LogicalDriveNumber].LogicalDriveSize); + } + else + { + DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo = + Controller->V2.LogicalDeviceInformation[LogicalDriveNumber]; + if (LogicalDeviceInfo == NULL) return; + register_disk(&Controller->GenericDiskInfo, + DAC960_KernelDevice(Controller->ControllerNumber, + LogicalDriveNumber, 0), + DAC960_MaxPartitions, &DAC960_BlockDeviceOperations, + LogicalDeviceInfo + ->ConfigurableDeviceSizeIn512ByteBlocksOrMB); } - else DAC960_FinalizeController(Controller); } /* - DAC960_FinalizeController finalizes Controller. -*/ + DAC960_ReportErrorStatus reports Controller BIOS Messages passed through + the Error Status Register when the driver performs the BIOS handshaking. + It returns true for fatal errors and false otherwise. +*/ + +static boolean DAC960_ReportErrorStatus(DAC960_Controller_T *Controller, + unsigned char ErrorStatus, + unsigned char Parameter0, + unsigned char Parameter1) +{ + switch (ErrorStatus) + { + case 0x00: + DAC960_Notice("Physical Device %d:%d Not Responding\n", + Controller, Parameter1, Parameter0); + break; + case 0x08: + if (Controller->DriveSpinUpMessageDisplayed) break; + DAC960_Notice("Spinning Up Drives\n", Controller); + Controller->DriveSpinUpMessageDisplayed = true; + break; + case 0x30: + DAC960_Notice("Configuration Checksum Error\n", Controller); + break; + case 0x60: + DAC960_Notice("Mirror Race Recovery Failed\n", Controller); + break; + case 0x70: + DAC960_Notice("Mirror Race Recovery In Progress\n", Controller); + break; + case 0x90: + DAC960_Notice("Physical Device %d:%d COD Mismatch\n", + Controller, Parameter1, Parameter0); + break; + case 0xA0: + DAC960_Notice("Logical Drive Installation Aborted\n", Controller); + break; + case 0xB0: + DAC960_Notice("Mirror Race On A Critical Logical Drive\n", Controller); + break; + case 0xD0: + DAC960_Notice("New Controller Configuration Found\n", Controller); + break; + case 0xF0: + DAC960_Error("Fatal Memory Parity Error for Controller at\n", Controller); + return true; + default: + DAC960_Error("Unknown Initialization Error %02X for Controller at\n", + Controller, ErrorStatus); + return true; + } + return false; +} + + +/* + DAC960_DetectControllers detects Mylex DAC960/AcceleRAID/eXtremeRAID + PCI RAID Controllers by interrogating the PCI Configuration Space for + Controller Type. +*/ + +static void DAC960_DetectControllers(DAC960_HardwareType_T HardwareType) +{ + void (*InterruptHandler)(int, void *, Registers_T *) = NULL; + DAC960_FirmwareType_T FirmwareType = 0; + unsigned short VendorID = 0, DeviceID = 0; + unsigned int MemoryWindowSize = 0; + PCI_Device_T *PCI_Device = NULL; + switch (HardwareType) + { + case DAC960_BA_Controller: + VendorID = PCI_VENDOR_ID_MYLEX; + DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_BA; + FirmwareType = DAC960_V2_Controller; + InterruptHandler = DAC960_BA_InterruptHandler; + MemoryWindowSize = DAC960_BA_RegisterWindowSize; + break; + case DAC960_LP_Controller: + VendorID = PCI_VENDOR_ID_MYLEX; + DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_LP; + FirmwareType = DAC960_LP_Controller; + InterruptHandler = DAC960_LP_InterruptHandler; + MemoryWindowSize = DAC960_LP_RegisterWindowSize; + break; + case DAC960_LA_Controller: + VendorID = PCI_VENDOR_ID_DEC; + DeviceID = PCI_DEVICE_ID_DEC_21285; + FirmwareType = DAC960_V1_Controller; + InterruptHandler = DAC960_LA_InterruptHandler; + MemoryWindowSize = DAC960_LA_RegisterWindowSize; + break; + case DAC960_PG_Controller: + VendorID = PCI_VENDOR_ID_MYLEX; + DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_PG; + FirmwareType = DAC960_V1_Controller; + InterruptHandler = DAC960_PG_InterruptHandler; + MemoryWindowSize = DAC960_PG_RegisterWindowSize; + break; + case DAC960_PD_Controller: + VendorID = PCI_VENDOR_ID_MYLEX; + DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_PD; + FirmwareType = DAC960_V1_Controller; + InterruptHandler = DAC960_PD_InterruptHandler; + MemoryWindowSize = DAC960_PD_RegisterWindowSize; + break; + } + while ((PCI_Device = pci_find_device(VendorID, DeviceID, PCI_Device)) != NULL) + { + DAC960_Controller_T *Controller = NULL; + DAC960_IO_Address_T IO_Address = 0; + DAC960_PCI_Address_T PCI_Address = 0; + unsigned char Bus = PCI_Device->bus->number; + unsigned char DeviceFunction = PCI_Device->devfn; + unsigned char Device = DeviceFunction >> 3; + unsigned char Function = DeviceFunction & 0x7; + unsigned char ErrorStatus, Parameter0, Parameter1; + unsigned int IRQ_Channel = PCI_Device->irq; + void *BaseAddress; + if (pci_enable_device(PCI_Device) != 0) continue; + switch (HardwareType) + { + case DAC960_BA_Controller: + PCI_Address = pci_resource_start(PCI_Device, 0); + break; + case DAC960_LP_Controller: + PCI_Address = pci_resource_start(PCI_Device, 0); + break; + case DAC960_LA_Controller: + if (!(PCI_Device->subsystem_vendor == PCI_VENDOR_ID_MYLEX && + PCI_Device->subsystem_device == PCI_DEVICE_ID_MYLEX_DAC960_LA)) + continue; + PCI_Address = pci_resource_start(PCI_Device, 0); + break; + case DAC960_PG_Controller: + PCI_Address = pci_resource_start(PCI_Device, 0); + break; + case DAC960_PD_Controller: + IO_Address = pci_resource_start(PCI_Device, 0); + PCI_Address = pci_resource_start(PCI_Device, 1); + break; + } + if (DAC960_ControllerCount == DAC960_MaxControllers) + { + DAC960_Error("More than %d DAC960 Controllers detected - " + "ignoring from Controller at\n", + NULL, DAC960_MaxControllers); + goto Failure; + } + Controller = (DAC960_Controller_T *) + kmalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC); + if (Controller == NULL) + { + DAC960_Error("Unable to allocate Controller structure for " + "Controller at\n", NULL); + goto Failure; + } + memset(Controller, 0, sizeof(DAC960_Controller_T)); + Controller->ControllerNumber = DAC960_ControllerCount; + init_waitqueue_head(&Controller->CommandWaitQueue); + init_waitqueue_head(&Controller->HealthStatusWaitQueue); + DAC960_Controllers[DAC960_ControllerCount++] = Controller; + DAC960_AnnounceDriver(Controller); + Controller->FirmwareType = FirmwareType; + Controller->HardwareType = HardwareType; + Controller->IO_Address = IO_Address; + Controller->PCI_Address = PCI_Address; + Controller->Bus = Bus; + Controller->Device = Device; + Controller->Function = Function; + sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber); + /* + Map the Controller Register Window. + */ + if (MemoryWindowSize < PAGE_SIZE) + MemoryWindowSize = PAGE_SIZE; + Controller->MemoryMappedAddress = + ioremap_nocache(PCI_Address & PAGE_MASK, MemoryWindowSize); + Controller->BaseAddress = + Controller->MemoryMappedAddress + (PCI_Address & ~PAGE_MASK); + if (Controller->MemoryMappedAddress == NULL) + { + DAC960_Error("Unable to map Controller Register Window for " + "Controller at\n", Controller); + goto Failure; + } + BaseAddress = Controller->BaseAddress; + switch (HardwareType) + { + case DAC960_BA_Controller: + DAC960_BA_DisableInterrupts(Controller->BaseAddress); + DAC960_BA_AcknowledgeHardwareMailboxStatus(BaseAddress); + udelay(1000); + while (DAC960_BA_InitializationInProgressP(BaseAddress)) + { + if (DAC960_BA_ReadErrorStatus(BaseAddress, &ErrorStatus, + &Parameter0, &Parameter1) && + DAC960_ReportErrorStatus(Controller, ErrorStatus, + Parameter0, Parameter1)) + goto Failure; + udelay(10); + } + if (!DAC960_V2_EnableMemoryMailboxInterface(Controller)) + { + DAC960_Error("Unable to Enable Memory Mailbox Interface " + "for Controller at\n", Controller); + goto Failure; + } + DAC960_BA_EnableInterrupts(Controller->BaseAddress); + Controller->QueueCommand = DAC960_BA_QueueCommand; + Controller->ReadControllerConfiguration = + DAC960_V2_ReadControllerConfiguration; + Controller->ReadDeviceConfiguration = + DAC960_V2_ReadDeviceConfiguration; + Controller->ReportDeviceConfiguration = + DAC960_V2_ReportDeviceConfiguration; + Controller->QueueReadWriteCommand = + DAC960_V2_QueueReadWriteCommand; + break; + case DAC960_LP_Controller: + DAC960_LP_DisableInterrupts(Controller->BaseAddress); + DAC960_LP_AcknowledgeHardwareMailboxStatus(BaseAddress); + udelay(1000); + while (DAC960_LP_InitializationInProgressP(BaseAddress)) + { + if (DAC960_LP_ReadErrorStatus(BaseAddress, &ErrorStatus, + &Parameter0, &Parameter1) && + DAC960_ReportErrorStatus(Controller, ErrorStatus, + Parameter0, Parameter1)) + goto Failure; + udelay(10); + } + if (!DAC960_V2_EnableMemoryMailboxInterface(Controller)) + { + DAC960_Error("Unable to Enable Memory Mailbox Interface " + "for Controller at\n", Controller); + goto Failure; + } + DAC960_LP_EnableInterrupts(Controller->BaseAddress); + Controller->QueueCommand = DAC960_LP_QueueCommand; + Controller->ReadControllerConfiguration = + DAC960_V2_ReadControllerConfiguration; + Controller->ReadDeviceConfiguration = + DAC960_V2_ReadDeviceConfiguration; + Controller->ReportDeviceConfiguration = + DAC960_V2_ReportDeviceConfiguration; + Controller->QueueReadWriteCommand = + DAC960_V2_QueueReadWriteCommand; + break; + case DAC960_LA_Controller: + DAC960_LA_DisableInterrupts(Controller->BaseAddress); + DAC960_LA_AcknowledgeHardwareMailboxStatus(BaseAddress); + udelay(1000); + while (DAC960_LA_InitializationInProgressP(BaseAddress)) + { + if (DAC960_LA_ReadErrorStatus(BaseAddress, &ErrorStatus, + &Parameter0, &Parameter1) && + DAC960_ReportErrorStatus(Controller, ErrorStatus, + Parameter0, Parameter1)) + goto Failure; + udelay(10); + } + if (!DAC960_V1_EnableMemoryMailboxInterface(Controller)) + { + DAC960_Error("Unable to Enable Memory Mailbox Interface " + "for Controller at\n", Controller); + goto Failure; + } + DAC960_LA_EnableInterrupts(Controller->BaseAddress); + if (Controller->V1.DualModeMemoryMailboxInterface) + Controller->QueueCommand = DAC960_LA_QueueCommandDualMode; + else Controller->QueueCommand = DAC960_LA_QueueCommandSingleMode; + Controller->ReadControllerConfiguration = + DAC960_V1_ReadControllerConfiguration; + Controller->ReadDeviceConfiguration = + DAC960_V1_ReadDeviceConfiguration; + Controller->ReportDeviceConfiguration = + DAC960_V1_ReportDeviceConfiguration; + Controller->QueueReadWriteCommand = + DAC960_V1_QueueReadWriteCommand; + break; + case DAC960_PG_Controller: + DAC960_PG_DisableInterrupts(Controller->BaseAddress); + DAC960_PG_AcknowledgeHardwareMailboxStatus(BaseAddress); + udelay(1000); + while (DAC960_PG_InitializationInProgressP(BaseAddress)) + { + if (DAC960_PG_ReadErrorStatus(BaseAddress, &ErrorStatus, + &Parameter0, &Parameter1) && + DAC960_ReportErrorStatus(Controller, ErrorStatus, + Parameter0, Parameter1)) + goto Failure; + udelay(10); + } + if (!DAC960_V1_EnableMemoryMailboxInterface(Controller)) + { + DAC960_Error("Unable to Enable Memory Mailbox Interface " + "for Controller at\n", Controller); + goto Failure; + } + DAC960_PG_EnableInterrupts(Controller->BaseAddress); + if (Controller->V1.DualModeMemoryMailboxInterface) + Controller->QueueCommand = DAC960_PG_QueueCommandDualMode; + else Controller->QueueCommand = DAC960_PG_QueueCommandSingleMode; + Controller->ReadControllerConfiguration = + DAC960_V1_ReadControllerConfiguration; + Controller->ReadDeviceConfiguration = + DAC960_V1_ReadDeviceConfiguration; + Controller->ReportDeviceConfiguration = + DAC960_V1_ReportDeviceConfiguration; + Controller->QueueReadWriteCommand = + DAC960_V1_QueueReadWriteCommand; + break; + case DAC960_PD_Controller: + request_region(Controller->IO_Address, 0x80, + Controller->FullModelName); + DAC960_PD_DisableInterrupts(BaseAddress); + DAC960_PD_AcknowledgeStatus(BaseAddress); + udelay(1000); + while (DAC960_PD_InitializationInProgressP(BaseAddress)) + { + if (DAC960_PD_ReadErrorStatus(BaseAddress, &ErrorStatus, + &Parameter0, &Parameter1) && + DAC960_ReportErrorStatus(Controller, ErrorStatus, + Parameter0, Parameter1)) + goto Failure; + udelay(10); + } + DAC960_PD_EnableInterrupts(Controller->BaseAddress); + Controller->QueueCommand = DAC960_PD_QueueCommand; + Controller->ReadControllerConfiguration = + DAC960_V1_ReadControllerConfiguration; + Controller->ReadDeviceConfiguration = + DAC960_V1_ReadDeviceConfiguration; + Controller->ReportDeviceConfiguration = + DAC960_V1_ReportDeviceConfiguration; + Controller->QueueReadWriteCommand = + DAC960_V1_QueueReadWriteCommand; + break; + } + /* + Acquire shared access to the IRQ Channel. + */ + if (IRQ_Channel == 0) + { + DAC960_Error("IRQ Channel %d illegal for Controller at\n", + Controller, IRQ_Channel); + goto Failure; + } + strcpy(Controller->FullModelName, "DAC960"); + if (request_irq(IRQ_Channel, InterruptHandler, SA_SHIRQ, + Controller->FullModelName, Controller) < 0) + { + DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n", + Controller, IRQ_Channel); + goto Failure; + } + Controller->IRQ_Channel = IRQ_Channel; + DAC960_ActiveControllerCount++; + Controller->InitialCommand.CommandIdentifier = 1; + Controller->InitialCommand.Controller = Controller; + Controller->Commands[0] = &Controller->InitialCommand; + Controller->FreeCommands = &Controller->InitialCommand; + Controller->ControllerDetectionSuccessful = true; + continue; + Failure: + if (IO_Address == 0) + DAC960_Error("PCI Bus %d Device %d Function %d I/O Address N/A " + "PCI Address 0x%X\n", Controller, + Bus, Device, Function, PCI_Address); + else DAC960_Error("PCI Bus %d Device %d Function %d I/O Address " + "0x%X PCI Address 0x%X\n", Controller, + Bus, Device, Function, IO_Address, PCI_Address); + if (Controller == NULL) break; + if (Controller->MemoryMappedAddress != NULL) + iounmap(Controller->MemoryMappedAddress); + if (Controller->IRQ_Channel > 0) + free_irq(IRQ_Channel, Controller); + } +} + + +/* + DAC960_SortControllers sorts the Controllers by PCI Bus and Device Number. +*/ + +static void DAC960_SortControllers(void) +{ + int ControllerNumber, LastInterchange, Bound, j; + LastInterchange = DAC960_ControllerCount-1; + while (LastInterchange > 0) + { + Bound = LastInterchange; + LastInterchange = 0; + for (j = 0; j < Bound; j++) + { + DAC960_Controller_T *Controller1 = DAC960_Controllers[j]; + DAC960_Controller_T *Controller2 = DAC960_Controllers[j+1]; + if (Controller1->Bus > Controller2->Bus || + (Controller1->Bus == Controller2->Bus && + (Controller1->Device > Controller2->Device))) + { + Controller2->ControllerNumber = j; + DAC960_Controllers[j] = Controller2; + Controller1->ControllerNumber = j+1; + DAC960_Controllers[j+1] = Controller1; + LastInterchange = j; + } + } + } + for (ControllerNumber = 0; + ControllerNumber < DAC960_ControllerCount; + ControllerNumber++) + { + DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; + if (!Controller->ControllerDetectionSuccessful) + { + DAC960_Controllers[ControllerNumber] = NULL; + kfree(Controller); + } + } +} + + +/* + DAC960_InitializeController initializes Controller. +*/ + +static void DAC960_InitializeController(DAC960_Controller_T *Controller) +{ + if (DAC960_ReadControllerConfiguration(Controller) && + DAC960_ReportControllerConfiguration(Controller) && + DAC960_CreateAuxiliaryStructures(Controller) && + DAC960_ReadDeviceConfiguration(Controller) && + DAC960_ReportDeviceConfiguration(Controller) && + DAC960_RegisterBlockDevice(Controller)) + { + /* + Initialize the Monitoring Timer. + */ + init_timer(&Controller->MonitoringTimer); + Controller->MonitoringTimer.expires = + jiffies + DAC960_MonitoringTimerInterval; + Controller->MonitoringTimer.data = (unsigned long) Controller; + Controller->MonitoringTimer.function = DAC960_MonitoringTimerFunction; + add_timer(&Controller->MonitoringTimer); + Controller->ControllerInitialized = true; + } + else DAC960_FinalizeController(Controller); +} + + +/* + DAC960_FinalizeController finalizes Controller. +*/ static void DAC960_FinalizeController(DAC960_Controller_T *Controller) { if (Controller->ControllerInitialized) { del_timer(&Controller->MonitoringTimer); - DAC960_Notice("Flushing Cache...", Controller); - DAC960_ExecuteType3(Controller, DAC960_Flush, NULL); - DAC960_Notice("done\n", Controller); - switch (Controller->ControllerType) - { - case DAC960_V5_Controller: - if (!Controller->DualModeMemoryMailboxInterface) - DAC960_V5_SaveMemoryMailboxInfo(Controller); - break; - case DAC960_V4_Controller: - if (!Controller->DualModeMemoryMailboxInterface) - DAC960_V4_SaveMemoryMailboxInfo(Controller); - break; - case DAC960_V3_Controller: - break; + if (Controller->FirmwareType == DAC960_V1_Controller) + { + DAC960_Notice("Flushing Cache...", Controller); + DAC960_V1_ExecuteType3(Controller, DAC960_V1_Flush, NULL); + DAC960_Notice("done\n", Controller); + switch (Controller->HardwareType) + { + case DAC960_LA_Controller: + if (Controller->V1.DualModeMemoryMailboxInterface) + free_pages(Controller->MemoryMailboxPagesAddress, + Controller->MemoryMailboxPagesOrder); + else DAC960_LA_SaveMemoryMailboxInfo(Controller); + break; + case DAC960_PG_Controller: + if (Controller->V1.DualModeMemoryMailboxInterface) + free_pages(Controller->MemoryMailboxPagesAddress, + Controller->MemoryMailboxPagesOrder); + else DAC960_PG_SaveMemoryMailboxInfo(Controller); + break; + case DAC960_PD_Controller: + release_region(Controller->IO_Address, 0x80); + break; + default: + break; + } + } + else + { + DAC960_Notice("Flushing Cache...", Controller); + DAC960_V2_DeviceOperation(Controller, DAC960_V2_PauseDevice, + DAC960_V2_RAID_Controller); + DAC960_Notice("done\n", Controller); + free_pages(Controller->MemoryMailboxPagesAddress, + Controller->MemoryMailboxPagesOrder); } } free_irq(Controller->IRQ_Channel, Controller); iounmap(Controller->MemoryMappedAddress); - if (Controller->IO_Address > 0) - release_region(Controller->IO_Address, 0x80); DAC960_UnregisterBlockDevice(Controller); + DAC960_DestroyAuxiliaryStructures(Controller); DAC960_Controllers[Controller->ControllerNumber] = NULL; kfree(Controller); } @@ -1397,15 +2549,26 @@ void DAC960_Initialize(void) { int ControllerNumber; - DAC960_DetectControllers(DAC960_V5_Controller); - DAC960_DetectControllers(DAC960_V4_Controller); - DAC960_DetectControllers(DAC960_V3_Controller); + DAC960_DetectControllers(DAC960_BA_Controller); + DAC960_DetectControllers(DAC960_LP_Controller); + DAC960_DetectControllers(DAC960_LA_Controller); + DAC960_DetectControllers(DAC960_PG_Controller); + DAC960_DetectControllers(DAC960_PD_Controller); + DAC960_SortControllers(); if (DAC960_ActiveControllerCount == 0) return; for (ControllerNumber = 0; ControllerNumber < DAC960_ControllerCount; ControllerNumber++) - if (DAC960_Controllers[ControllerNumber] != NULL) - DAC960_InitializeController(DAC960_Controllers[ControllerNumber]); + { + DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; + int LogicalDriveNumber; + if (Controller == NULL) continue; + DAC960_InitializeController(Controller); + for (LogicalDriveNumber = 0; + LogicalDriveNumber < DAC960_MaxLogicalDrives; + LogicalDriveNumber++) + DAC960_RegisterDisk(Controller, LogicalDriveNumber); + } DAC960_CreateProcEntries(); register_reboot_notifier(&DAC960_NotifierBlock); } @@ -1435,69 +2598,38 @@ /* - DAC960_ProcessRequest attempts to remove one I/O Request from Controller's - I/O Request Queue and queues it to the Controller. WaitForCommand is true if - this function should wait for a Command to become available if necessary. - This function returns true if an I/O Request was queued and false otherwise. + DAC960_V1_QueueReadWriteCommand prepares and queues a Read/Write Command for + DAC960 V1 Firmware Controllers. */ -static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller, - boolean WaitForCommand) +static void DAC960_V1_QueueReadWriteCommand(DAC960_Command_T *Command) { - struct list_head * queue_head; - IO_Request_T *Request; - DAC960_Command_T *Command; - char *RequestBuffer; - - queue_head = &blk_dev[DAC960_MAJOR + Controller->ControllerNumber].request_queue.queue_head; - while (true) - { - if (list_empty(queue_head)) return false; - Request = blkdev_entry_next_request(queue_head); - if (Request->rq_status == RQ_INACTIVE) return false; - Command = DAC960_AllocateCommand(Controller); - if (Command != NULL) break; - if (!WaitForCommand) return false; - DAC960_WaitForCommand(Controller); - } - DAC960_ClearCommand(Command); - if (Request->cmd == READ) - Command->CommandType = DAC960_ReadCommand; - else Command->CommandType = DAC960_WriteCommand; - Command->Semaphore = Request->sem; - Command->LogicalDriveNumber = DAC960_LogicalDriveNumber(Request->rq_dev); - Command->BlockNumber = - Request->sector - + Controller->GenericDiskInfo.part[MINOR(Request->rq_dev)].start_sect; - Command->BlockCount = Request->nr_sectors; - Command->SegmentCount = Request->nr_segments; - Command->BufferHeader = Request->bh; - RequestBuffer = Request->buffer; - blkdev_dequeue_request(Request); - blkdev_release_request(Request); + DAC960_Controller_T *Controller = Command->Controller; + DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + DAC960_V1_ClearCommand(Command); if (Command->SegmentCount == 1) { - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; if (Command->CommandType == DAC960_ReadCommand) - CommandMailbox->Type5.CommandOpcode = DAC960_Read; - else CommandMailbox->Type5.CommandOpcode = DAC960_Write; + CommandMailbox->Type5.CommandOpcode = DAC960_V1_Read; + else CommandMailbox->Type5.CommandOpcode = DAC960_V1_Write; CommandMailbox->Type5.LD.TransferLength = Command->BlockCount; CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber; CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber; - CommandMailbox->Type5.BusAddress = Virtual_to_Bus(RequestBuffer); + CommandMailbox->Type5.BusAddress = Virtual_to_Bus(Command->RequestBuffer); } else { - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; - DAC960_ScatterGatherSegment_T - *ScatterGatherList = Command->ScatterGatherList; + DAC960_V1_ScatterGatherSegment_T + *ScatterGatherList = Command->V1.ScatterGatherList; BufferHeader_T *BufferHeader = Command->BufferHeader; char *LastDataEndPointer = NULL; int SegmentNumber = 0; if (Command->CommandType == DAC960_ReadCommand) - CommandMailbox->Type5.CommandOpcode = DAC960_ReadWithOldScatterGather; + CommandMailbox->Type5.CommandOpcode = + DAC960_V1_ReadWithOldScatterGather; else - CommandMailbox->Type5.CommandOpcode = DAC960_WriteWithOldScatterGather; + CommandMailbox->Type5.CommandOpcode = + DAC960_V1_WriteWithOldScatterGather; CommandMailbox->Type5.LD.TransferLength = Command->BlockCount; CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber; CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber; @@ -1518,7 +2650,7 @@ ScatterGatherList[SegmentNumber].SegmentByteCount = BufferHeader->b_size; LastDataEndPointer = BufferHeader->b_data + BufferHeader->b_size; - if (SegmentNumber++ > Controller->MaxScatterGatherSegments) + if (SegmentNumber++ > Controller->DriverScatterGatherLimit) panic("DAC960: Scatter/Gather Segment Overflow\n"); } BufferHeader = BufferHeader->b_reqnext; @@ -1527,167 +2659,163 @@ panic("DAC960: SegmentNumber != SegmentCount\n"); } DAC960_QueueCommand(Command); - return true; -} - - -/* - DAC960_ProcessRequests attempts to remove as many I/O Requests as possible - from Controller's I/O Request Queue and queue them to the Controller. -*/ - -static inline void DAC960_ProcessRequests(DAC960_Controller_T *Controller) -{ - int Counter = 0; - while (DAC960_ProcessRequest(Controller, Counter++ == 0)) ; -} - - -/* - DAC960_RequestFunction0 is the I/O Request Function for DAC960 Controller 0. -*/ - -static void DAC960_RequestFunction0(request_queue_t * q) -{ - DAC960_Controller_T *Controller = DAC960_Controllers[0]; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); - /* - Process I/O Requests for Controller. - */ - DAC960_ProcessRequests(Controller); - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); -} - - -/* - DAC960_RequestFunction1 is the I/O Request Function for DAC960 Controller 1. -*/ - -static void DAC960_RequestFunction1(request_queue_t * q) -{ - DAC960_Controller_T *Controller = DAC960_Controllers[1]; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); - /* - Process I/O Requests for Controller. - */ - DAC960_ProcessRequests(Controller); - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); -} - - -/* - DAC960_RequestFunction2 is the I/O Request Function for DAC960 Controller 2. -*/ - -static void DAC960_RequestFunction2(request_queue_t * q) -{ - DAC960_Controller_T *Controller = DAC960_Controllers[2]; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); - /* - Process I/O Requests for Controller. - */ - DAC960_ProcessRequests(Controller); - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); } /* - DAC960_RequestFunction3 is the I/O Request Function for DAC960 Controller 3. + DAC960_V2_QueueReadWriteCommand prepares and queues a Read/Write Command for + DAC960 V2 Firmware Controllers. */ -static void DAC960_RequestFunction3(request_queue_t * q) +static void DAC960_V2_QueueReadWriteCommand(DAC960_Command_T *Command) { - DAC960_Controller_T *Controller = DAC960_Controllers[3]; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); - /* - Process I/O Requests for Controller. - */ - DAC960_ProcessRequests(Controller); - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); + DAC960_Controller_T *Controller = Command->Controller; + DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_ClearCommand(Command); + CommandMailbox->SCSI_10.CommandOpcode = DAC960_V2_SCSI_10; + CommandMailbox->SCSI_10.CommandControlBits.DataTransferControllerToHost = + (Command->CommandType == DAC960_ReadCommand); + CommandMailbox->SCSI_10.DataTransferSize = + Command->BlockCount << DAC960_BlockSizeBits; + CommandMailbox->SCSI_10.RequestSenseBusAddress = + Virtual_to_Bus(&Command->V2.RequestSense); + CommandMailbox->SCSI_10.PhysicalDevice = + Controller->V2.LogicalDriveToVirtualDevice[Command->LogicalDriveNumber]; + CommandMailbox->SCSI_10.RequestSenseSize = + sizeof(DAC960_SCSI_RequestSense_T); + CommandMailbox->SCSI_10.CDBLength = 10; + CommandMailbox->SCSI_10.SCSI_CDB[0] = + (Command->CommandType == DAC960_ReadCommand ? 0x28 : 0x2A); + CommandMailbox->SCSI_10.SCSI_CDB[2] = Command->BlockNumber >> 24; + CommandMailbox->SCSI_10.SCSI_CDB[3] = Command->BlockNumber >> 16; + CommandMailbox->SCSI_10.SCSI_CDB[4] = Command->BlockNumber >> 8; + CommandMailbox->SCSI_10.SCSI_CDB[5] = Command->BlockNumber; + CommandMailbox->SCSI_10.SCSI_CDB[7] = Command->BlockCount >> 8; + CommandMailbox->SCSI_10.SCSI_CDB[8] = Command->BlockCount; + if (Command->SegmentCount == 1) + { + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(Command->RequestBuffer); + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->SCSI_10.DataTransferSize; + } + else + { + DAC960_V2_ScatterGatherSegment_T + *ScatterGatherList = Command->V2.ScatterGatherList; + BufferHeader_T *BufferHeader = Command->BufferHeader; + char *LastDataEndPointer = NULL; + int SegmentNumber = 0; + if (Command->SegmentCount > 2) + { + CommandMailbox->SCSI_10.CommandControlBits + .AdditionalScatterGatherListMemory = true; + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ExtendedScatterGather.ScatterGatherList0Length = + Command->SegmentCount; + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ExtendedScatterGather.ScatterGatherList0Address = + Virtual_to_Bus(ScatterGatherList); + } + else + ScatterGatherList = + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments; + while (BufferHeader != NULL) + { + if (BufferHeader->b_data == LastDataEndPointer) + { + ScatterGatherList[SegmentNumber-1].SegmentByteCount += + BufferHeader->b_size; + LastDataEndPointer += BufferHeader->b_size; + } + else + { + ScatterGatherList[SegmentNumber].SegmentDataPointer = + Virtual_to_Bus(BufferHeader->b_data); + ScatterGatherList[SegmentNumber].SegmentByteCount = + BufferHeader->b_size; + LastDataEndPointer = BufferHeader->b_data + BufferHeader->b_size; + if (SegmentNumber++ > Controller->DriverScatterGatherLimit) + panic("DAC960: Scatter/Gather Segment Overflow\n"); + } + BufferHeader = BufferHeader->b_reqnext; + } + if (SegmentNumber != Command->SegmentCount) + panic("DAC960: SegmentNumber != SegmentCount\n"); + } + DAC960_QueueCommand(Command); } /* - DAC960_RequestFunction4 is the I/O Request Function for DAC960 Controller 4. + DAC960_ProcessRequest attempts to remove one I/O Request from Controller's + I/O Request Queue and queues it to the Controller. WaitForCommand is true if + this function should wait for a Command to become available if necessary. + This function returns true if an I/O Request was queued and false otherwise. */ -static void DAC960_RequestFunction4(request_queue_t * q) +static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller, + boolean WaitForCommand) { - DAC960_Controller_T *Controller = DAC960_Controllers[4]; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); - /* - Process I/O Requests for Controller. - */ - DAC960_ProcessRequests(Controller); - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); + RequestQueue_T *RequestQueue = Controller->RequestQueue; + ListHead_T *RequestQueueHead; + IO_Request_T *Request; + DAC960_Command_T *Command; + if (RequestQueue == NULL) return false; + RequestQueueHead = &RequestQueue->queue_head; + while (true) + { + if (list_empty(RequestQueueHead)) return false; + Request = blkdev_entry_next_request(RequestQueueHead); + Command = DAC960_AllocateCommand(Controller); + if (Command != NULL) break; + if (!WaitForCommand) return false; + DAC960_WaitForCommand(Controller); + } + if (Request->cmd == READ) + Command->CommandType = DAC960_ReadCommand; + else Command->CommandType = DAC960_WriteCommand; + Command->Semaphore = Request->sem; + Command->LogicalDriveNumber = DAC960_LogicalDriveNumber(Request->rq_dev); + Command->BlockNumber = + Request->sector + + Controller->GenericDiskInfo.part[MINOR(Request->rq_dev)].start_sect; + Command->BlockCount = Request->nr_sectors; + Command->SegmentCount = Request->nr_segments; + Command->BufferHeader = Request->bh; + Command->RequestBuffer = Request->buffer; + blkdev_dequeue_request(Request); + blkdev_release_request(Request); + DAC960_QueueReadWriteCommand(Command); + return true; } /* - DAC960_RequestFunction5 is the I/O Request Function for DAC960 Controller 5. + DAC960_ProcessRequests attempts to remove as many I/O Requests as possible + from Controller's I/O Request Queue and queue them to the Controller. */ -static void DAC960_RequestFunction5(request_queue_t * q) +static inline void DAC960_ProcessRequests(DAC960_Controller_T *Controller) { - DAC960_Controller_T *Controller = DAC960_Controllers[5]; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); - /* - Process I/O Requests for Controller. - */ - DAC960_ProcessRequests(Controller); - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); + int Counter = 0; + while (DAC960_ProcessRequest(Controller, Counter++ == 0)) ; } /* - DAC960_RequestFunction6 is the I/O Request Function for DAC960 Controller 6. + DAC960_RequestFunction is the I/O Request Function for DAC960 Controllers. */ -static void DAC960_RequestFunction6(request_queue_t * q) +static void DAC960_RequestFunction(RequestQueue_T *RequestQueue) { - DAC960_Controller_T *Controller = DAC960_Controllers[6]; + DAC960_Controller_T *Controller = + (DAC960_Controller_T *) RequestQueue->queuedata; ProcessorFlags_T ProcessorFlags; /* Acquire exclusive access to Controller. @@ -1705,37 +2833,26 @@ /* - DAC960_RequestFunction7 is the I/O Request Function for DAC960 Controller 7. + DAC960_ProcessCompletedBuffer performs completion processing for an + individual Buffer. */ -static void DAC960_RequestFunction7(request_queue_t * q) +static inline void DAC960_ProcessCompletedBuffer(BufferHeader_T *BufferHeader, + boolean SuccessfulIO) { - DAC960_Controller_T *Controller = DAC960_Controllers[7]; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); - /* - Process I/O Requests for Controller. - */ - DAC960_ProcessRequests(Controller); - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); + BufferHeader->b_end_io(BufferHeader, SuccessfulIO); } /* - DAC960_ReadWriteError prints an appropriate error message for Command when - an error occurs on a Read or Write operation. + DAC960_V1_ReadWriteError prints an appropriate error message for Command + when an error occurs on a Read or Write operation. */ -static void DAC960_ReadWriteError(DAC960_Command_T *Command) +static void DAC960_V1_ReadWriteError(DAC960_Command_T *Command) { DAC960_Controller_T *Controller = Command->Controller; - char *CommandName = "UNKNOWN"; + unsigned char *CommandName = "UNKNOWN"; switch (Command->CommandType) { case DAC960_ReadCommand: @@ -1751,26 +2868,26 @@ case DAC960_QueuedCommand: break; } - switch (Command->CommandStatus) + switch (Command->V1.CommandStatus) { - case DAC960_IrrecoverableDataError: + case DAC960_V1_IrrecoverableDataError: DAC960_Error("Irrecoverable Data Error on %s:\n", Controller, CommandName); break; - case DAC960_LogicalDriveNonexistentOrOffline: + case DAC960_V1_LogicalDriveNonexistentOrOffline: DAC960_Error("Logical Drive Nonexistent or Offline on %s:\n", Controller, CommandName); break; - case DAC960_AccessBeyondEndOfLogicalDrive: + case DAC960_V1_AccessBeyondEndOfLogicalDrive: DAC960_Error("Attempt to Access Beyond End of Logical Drive " "on %s:\n", Controller, CommandName); break; - case DAC960_BadDataEncountered: + case DAC960_V1_BadDataEncountered: DAC960_Error("Bad Data Encountered on %s:\n", Controller, CommandName); break; default: DAC960_Error("Unexpected Error Status %04X on %s:\n", - Controller, Command->CommandStatus, CommandName); + Controller, Command->V1.CommandStatus, CommandName); break; } DAC960_Error(" /dev/rd/c%dd%d: absolute blocks %d..%d\n", @@ -1788,33 +2905,22 @@ /* - DAC960_ProcessCompletedBuffer performs completion processing for an - individual Buffer. -*/ - -static inline void DAC960_ProcessCompletedBuffer(BufferHeader_T *BufferHeader, - boolean SuccessfulIO) -{ - BufferHeader->b_end_io(BufferHeader, SuccessfulIO); -} - - -/* - DAC960_ProcessCompletedCommand performs completion processing for Command. + DAC960_V1_ProcessCompletedCommand performs completion processing for Command + for DAC960 V1 Firmware Controllers. */ -static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) +static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command) { DAC960_Controller_T *Controller = Command->Controller; DAC960_CommandType_T CommandType = Command->CommandType; - DAC960_CommandOpcode_T CommandOpcode = - Command->CommandMailbox.Common.CommandOpcode; - DAC960_CommandStatus_T CommandStatus = Command->CommandStatus; + DAC960_V1_CommandOpcode_T CommandOpcode = + Command->V1.CommandMailbox.Common.CommandOpcode; + DAC960_V1_CommandStatus_T CommandStatus = Command->V1.CommandStatus; BufferHeader_T *BufferHeader = Command->BufferHeader; if (CommandType == DAC960_ReadCommand || CommandType == DAC960_WriteCommand) { - if (CommandStatus == DAC960_NormalCompletion) + if (CommandStatus == DAC960_V1_NormalCompletion) { /* Perform completion processing for all buffers in this I/O Request. @@ -1836,21 +2942,22 @@ } add_blkdev_randomness(DAC960_MAJOR + Controller->ControllerNumber); } - else if ((CommandStatus == DAC960_IrrecoverableDataError || - CommandStatus == DAC960_BadDataEncountered) && + else if ((CommandStatus == DAC960_V1_IrrecoverableDataError || + CommandStatus == DAC960_V1_BadDataEncountered) && BufferHeader != NULL && BufferHeader->b_reqnext != NULL) { - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; + DAC960_V1_CommandMailbox_T *CommandMailbox = + &Command->V1.CommandMailbox; if (CommandType == DAC960_ReadCommand) { Command->CommandType = DAC960_ReadRetryCommand; - CommandMailbox->Type5.CommandOpcode = DAC960_Read; + CommandMailbox->Type5.CommandOpcode = DAC960_V1_Read; } else { Command->CommandType = DAC960_WriteRetryCommand; - CommandMailbox->Type5.CommandOpcode = DAC960_Write; + CommandMailbox->Type5.CommandOpcode = DAC960_V1_Write; } Command->BlockCount = BufferHeader->b_size >> DAC960_BlockSizeBits; CommandMailbox->Type5.LD.TransferLength = Command->BlockCount; @@ -1861,8 +2968,8 @@ } else { - if (CommandStatus != DAC960_LogicalDriveNonexistentOrOffline) - DAC960_ReadWriteError(Command); + if (CommandStatus != DAC960_V1_LogicalDriveNonexistentOrOffline) + DAC960_V1_ReadWriteError(Command); /* Perform completion processing for all buffers in this I/O Request. */ @@ -1891,17 +2998,18 @@ /* Perform completion processing for this single buffer. */ - if (CommandStatus == DAC960_NormalCompletion) + if (CommandStatus == DAC960_V1_NormalCompletion) DAC960_ProcessCompletedBuffer(BufferHeader, true); else { - if (CommandStatus != DAC960_LogicalDriveNonexistentOrOffline) - DAC960_ReadWriteError(Command); + if (CommandStatus != DAC960_V1_LogicalDriveNonexistentOrOffline) + DAC960_V1_ReadWriteError(Command); DAC960_ProcessCompletedBuffer(BufferHeader, false); } if (NextBufferHeader != NULL) { - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; + DAC960_V1_CommandMailbox_T *CommandMailbox = + &Command->V1.CommandMailbox; Command->BlockNumber += BufferHeader->b_size >> DAC960_BlockSizeBits; Command->BlockCount = @@ -1916,30 +3024,43 @@ } } else if (CommandType == DAC960_MonitoringCommand || - CommandOpcode == DAC960_Enquiry || - CommandOpcode == DAC960_GetRebuildProgress) + CommandOpcode == DAC960_V1_Enquiry || + CommandOpcode == DAC960_V1_GetRebuildProgress) { if (CommandType != DAC960_MonitoringCommand) { - if (CommandOpcode == DAC960_Enquiry) - memcpy(&Controller->Enquiry[Controller->EnquiryIndex ^ 1], - Bus_to_Virtual(Command->CommandMailbox.Type3.BusAddress), - sizeof(DAC960_Enquiry_T)); - else if (CommandOpcode == DAC960_GetRebuildProgress) - memcpy(&Controller->RebuildProgress, - Bus_to_Virtual(Command->CommandMailbox.Type3.BusAddress), - sizeof(DAC960_RebuildProgress_T)); - } - if (CommandOpcode == DAC960_Enquiry) - { - DAC960_Enquiry_T *OldEnquiry = - &Controller->Enquiry[Controller->EnquiryIndex]; - DAC960_Enquiry_T *NewEnquiry = - &Controller->Enquiry[Controller->EnquiryIndex ^= 1]; + if (CommandOpcode == DAC960_V1_Enquiry) + memcpy(&Controller->V1.NewEnquiry, + Bus_to_Virtual(Command->V1.CommandMailbox.Type3.BusAddress), + sizeof(DAC960_V1_Enquiry_T)); + else if (CommandOpcode == DAC960_V1_GetRebuildProgress) + memcpy(&Controller->V1.RebuildProgress, + Bus_to_Virtual(Command->V1.CommandMailbox.Type3.BusAddress), + sizeof(DAC960_V1_RebuildProgress_T)); + } + if (CommandOpcode == DAC960_V1_Enquiry && + Controller->ControllerInitialized) + { + DAC960_V1_Enquiry_T *OldEnquiry = &Controller->V1.Enquiry; + DAC960_V1_Enquiry_T *NewEnquiry = &Controller->V1.NewEnquiry; unsigned int OldCriticalLogicalDriveCount = OldEnquiry->CriticalLogicalDriveCount; unsigned int NewCriticalLogicalDriveCount = NewEnquiry->CriticalLogicalDriveCount; + if (NewEnquiry->NumberOfLogicalDrives > Controller->LogicalDriveCount) + { + int LogicalDriveNumber = Controller->LogicalDriveCount; + while (LogicalDriveNumber < NewEnquiry->NumberOfLogicalDrives) + { + DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) " + "Now Exists\n", Controller, + LogicalDriveNumber, + Controller->ControllerNumber, + LogicalDriveNumber); + LogicalDriveNumber++; + } + Controller->LogicalDriveCount = LogicalDriveNumber; + } if (NewEnquiry->StatusFlags.DeferredWriteError != OldEnquiry->StatusFlags.DeferredWriteError) DAC960_Critical("Deferred Write Error Flag is now %s\n", Controller, @@ -1959,72 +3080,86 @@ (jiffies - Controller->SecondaryMonitoringTime >= DAC960_SecondaryMonitoringInterval)) { - Controller->NeedLogicalDriveInformation = true; - Controller->NewEventLogSequenceNumber = + Controller->V1.NeedLogicalDriveInformation = true; + Controller->V1.NewEventLogSequenceNumber = NewEnquiry->EventLogSequenceNumber; - Controller->NeedErrorTableInformation = true; - Controller->NeedDeviceStateInformation = true; - Controller->DeviceStateChannel = 0; - Controller->DeviceStateTargetID = -1; + Controller->V1.NeedErrorTableInformation = true; + Controller->V1.NeedDeviceStateInformation = true; + Controller->V1.DeviceStateChannel = 0; + Controller->V1.DeviceStateTargetID = -1; Controller->SecondaryMonitoringTime = jiffies; } - if (NewEnquiry->RebuildFlag == DAC960_StandbyRebuildInProgress || - NewEnquiry->RebuildFlag == DAC960_BackgroundRebuildInProgress || - OldEnquiry->RebuildFlag == DAC960_StandbyRebuildInProgress || - OldEnquiry->RebuildFlag == DAC960_BackgroundRebuildInProgress) - Controller->NeedRebuildProgress = true; - if (OldEnquiry->RebuildFlag == DAC960_BackgroundCheckInProgress) + if (NewEnquiry->RebuildFlag == DAC960_V1_StandbyRebuildInProgress || + NewEnquiry->RebuildFlag + == DAC960_V1_BackgroundRebuildInProgress || + OldEnquiry->RebuildFlag == DAC960_V1_StandbyRebuildInProgress || + OldEnquiry->RebuildFlag == DAC960_V1_BackgroundRebuildInProgress) + { + Controller->V1.NeedRebuildProgress = true; + Controller->V1.RebuildProgressFirst = + (NewEnquiry->CriticalLogicalDriveCount < + OldEnquiry->CriticalLogicalDriveCount); + } + if (OldEnquiry->RebuildFlag == DAC960_V1_BackgroundCheckInProgress) switch (NewEnquiry->RebuildFlag) { - case DAC960_NoStandbyRebuildOrCheckInProgress: + case DAC960_V1_NoStandbyRebuildOrCheckInProgress: DAC960_Progress("Consistency Check Completed Successfully\n", Controller); break; - case DAC960_StandbyRebuildInProgress: - case DAC960_BackgroundRebuildInProgress: + case DAC960_V1_StandbyRebuildInProgress: + case DAC960_V1_BackgroundRebuildInProgress: break; - case DAC960_BackgroundCheckInProgress: - Controller->NeedConsistencyCheckProgress = true; + case DAC960_V1_BackgroundCheckInProgress: + Controller->V1.NeedConsistencyCheckProgress = true; break; - case DAC960_StandbyRebuildCompletedWithError: + case DAC960_V1_StandbyRebuildCompletedWithError: DAC960_Progress("Consistency Check Completed with Error\n", Controller); break; - case DAC960_BackgroundRebuildOrCheckFailed_DriveFailed: + case DAC960_V1_BackgroundRebuildOrCheckFailed_DriveFailed: DAC960_Progress("Consistency Check Failed - " - "Physical Drive Failed\n", Controller); + "Physical Device Failed\n", Controller); break; - case DAC960_BackgroundRebuildOrCheckFailed_LogicalDriveFailed: + case DAC960_V1_BackgroundRebuildOrCheckFailed_LogicalDriveFailed: DAC960_Progress("Consistency Check Failed - " "Logical Drive Failed\n", Controller); break; - case DAC960_BackgroundRebuildOrCheckFailed_OtherCauses: + case DAC960_V1_BackgroundRebuildOrCheckFailed_OtherCauses: DAC960_Progress("Consistency Check Failed - Other Causes\n", Controller); break; - case DAC960_BackgroundRebuildOrCheckSuccessfullyTerminated: + case DAC960_V1_BackgroundRebuildOrCheckSuccessfullyTerminated: DAC960_Progress("Consistency Check Successfully Terminated\n", Controller); break; } - else if (NewEnquiry->RebuildFlag == DAC960_BackgroundCheckInProgress) - Controller->NeedConsistencyCheckProgress = true; + else if (NewEnquiry->RebuildFlag + == DAC960_V1_BackgroundCheckInProgress) + Controller->V1.NeedConsistencyCheckProgress = true; + Controller->MonitoringAlertMode = + (NewEnquiry->CriticalLogicalDriveCount > 0 || + NewEnquiry->OfflineLogicalDriveCount > 0 || + NewEnquiry->DeadDriveCount > 0); if (CommandType != DAC960_MonitoringCommand && - Controller->RebuildFlagPending) + Controller->V1.RebuildFlagPending) { - DAC960_Enquiry_T *Enquiry = (DAC960_Enquiry_T *) - Bus_to_Virtual(Command->CommandMailbox.Type3.BusAddress); - Enquiry->RebuildFlag = Controller->PendingRebuildFlag; - Controller->RebuildFlagPending = false; + DAC960_V1_Enquiry_T *Enquiry = (DAC960_V1_Enquiry_T *) + Bus_to_Virtual(Command->V1.CommandMailbox.Type3.BusAddress); + Enquiry->RebuildFlag = Controller->V1.PendingRebuildFlag; + Controller->V1.RebuildFlagPending = false; } else if (CommandType == DAC960_MonitoringCommand && - NewEnquiry->RebuildFlag > DAC960_BackgroundCheckInProgress) + NewEnquiry->RebuildFlag > + DAC960_V1_BackgroundCheckInProgress) { - Controller->PendingRebuildFlag = NewEnquiry->RebuildFlag; - Controller->RebuildFlagPending = true; + Controller->V1.PendingRebuildFlag = NewEnquiry->RebuildFlag; + Controller->V1.RebuildFlagPending = true; } + memcpy(&Controller->V1.Enquiry, &Controller->V1.NewEnquiry, + sizeof(DAC960_V1_Enquiry_T)); } - else if (CommandOpcode == DAC960_PerformEventLogOperation) + else if (CommandOpcode == DAC960_V1_PerformEventLogOperation) { static char *DAC960_EventMessages[] = @@ -2041,37 +3176,39 @@ "killed because of selection timeout", "killed due to SCSI phase sequence error", "killed due to unknown status" }; - DAC960_EventLogEntry_T *EventLogEntry = &Controller->EventLogEntry; + DAC960_V1_EventLogEntry_T *EventLogEntry = + &Controller->V1.EventLogEntry; if (EventLogEntry->SequenceNumber == - Controller->OldEventLogSequenceNumber) + Controller->V1.OldEventLogSequenceNumber) { unsigned char SenseKey = EventLogEntry->SenseKey; unsigned char AdditionalSenseCode = EventLogEntry->AdditionalSenseCode; unsigned char AdditionalSenseCodeQualifier = EventLogEntry->AdditionalSenseCodeQualifier; - if (SenseKey == 9 && + if (SenseKey == DAC960_SenseKey_VendorSpecific && AdditionalSenseCode == 0x80 && AdditionalSenseCodeQualifier < sizeof(DAC960_EventMessages) / sizeof(char *)) - DAC960_Critical("Physical Drive %d:%d %s\n", Controller, + DAC960_Critical("Physical Device %d:%d %s\n", Controller, EventLogEntry->Channel, EventLogEntry->TargetID, DAC960_EventMessages[ AdditionalSenseCodeQualifier]); - else if (SenseKey == 6 && AdditionalSenseCode == 0x29) + else if (SenseKey == DAC960_SenseKey_UnitAttention && + AdditionalSenseCode == 0x29) { if (Controller->MonitoringTimerCount > 0) - Controller->DeviceResetCount[EventLogEntry->Channel] - [EventLogEntry->TargetID]++; + Controller->V1.DeviceResetCount[EventLogEntry->Channel] + [EventLogEntry->TargetID]++; } - else if (!(SenseKey == 0 || - (SenseKey == 2 && + else if (!(SenseKey == DAC960_SenseKey_NoSense || + (SenseKey == DAC960_SenseKey_NotReady && AdditionalSenseCode == 0x04 && (AdditionalSenseCodeQualifier == 0x01 || AdditionalSenseCodeQualifier == 0x02)))) { - DAC960_Critical("Physical Drive %d:%d Error Log: " + DAC960_Critical("Physical Device %d:%d Error Log: " "Sense Key = %d, ASC = %02X, ASCQ = %02X\n", Controller, EventLogEntry->Channel, @@ -2079,7 +3216,7 @@ SenseKey, AdditionalSenseCode, AdditionalSenseCodeQualifier); - DAC960_Critical("Physical Drive %d:%d Error Log: " + DAC960_Critical("Physical Device %d:%d Error Log: " "Information = %02X%02X%02X%02X " "%02X%02X%02X%02X\n", Controller, @@ -2095,21 +3232,19 @@ EventLogEntry->CommandSpecificInformation[3]); } } - Controller->OldEventLogSequenceNumber++; + Controller->V1.OldEventLogSequenceNumber++; } - else if (CommandOpcode == DAC960_GetErrorTable) + else if (CommandOpcode == DAC960_V1_GetErrorTable) { - DAC960_ErrorTable_T *OldErrorTable = - &Controller->ErrorTable[Controller->ErrorTableIndex]; - DAC960_ErrorTable_T *NewErrorTable = - &Controller->ErrorTable[Controller->ErrorTableIndex ^= 1]; + DAC960_V1_ErrorTable_T *OldErrorTable = &Controller->V1.ErrorTable; + DAC960_V1_ErrorTable_T *NewErrorTable = &Controller->V1.NewErrorTable; int Channel, TargetID; for (Channel = 0; Channel < Controller->Channels; Channel++) - for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++) + for (TargetID = 0; TargetID < Controller->Targets; TargetID++) { - DAC960_ErrorTableEntry_T *NewErrorEntry = + DAC960_V1_ErrorTableEntry_T *NewErrorEntry = &NewErrorTable->ErrorTableEntries[Channel][TargetID]; - DAC960_ErrorTableEntry_T *OldErrorEntry = + DAC960_V1_ErrorTableEntry_T *OldErrorEntry = &OldErrorTable->ErrorTableEntries[Channel][TargetID]; if ((NewErrorEntry->ParityErrorCount != OldErrorEntry->ParityErrorCount) || @@ -2119,7 +3254,7 @@ OldErrorEntry->HardErrorCount) || (NewErrorEntry->MiscErrorCount != OldErrorEntry->MiscErrorCount)) - DAC960_Critical("Physical Drive %d:%d Errors: " + DAC960_Critical("Physical Device %d:%d Errors: " "Parity = %d, Soft = %d, " "Hard = %d, Misc = %d\n", Controller, Channel, TargetID, @@ -2128,51 +3263,49 @@ NewErrorEntry->HardErrorCount, NewErrorEntry->MiscErrorCount); } + memcpy(&Controller->V1.ErrorTable, &Controller->V1.NewErrorTable, + sizeof(DAC960_V1_ErrorTable_T)); } - else if (CommandOpcode == DAC960_GetDeviceState) + else if (CommandOpcode == DAC960_V1_GetDeviceState) { - DAC960_DeviceState_T *OldDeviceState = - &Controller->DeviceState[Controller->DeviceStateIndex] - [Controller->DeviceStateChannel] - [Controller->DeviceStateTargetID]; - DAC960_DeviceState_T *NewDeviceState = - &Controller->DeviceState[Controller->DeviceStateIndex ^ 1] - [Controller->DeviceStateChannel] - [Controller->DeviceStateTargetID]; + DAC960_V1_DeviceState_T *OldDeviceState = + &Controller->V1.DeviceState[Controller->V1.DeviceStateChannel] + [Controller->V1.DeviceStateTargetID]; + DAC960_V1_DeviceState_T *NewDeviceState = + &Controller->V1.NewDeviceState; if (NewDeviceState->DeviceState != OldDeviceState->DeviceState) - DAC960_Critical("Physical Drive %d:%d is now %s\n", Controller, - Controller->DeviceStateChannel, - Controller->DeviceStateTargetID, - (NewDeviceState->DeviceState == DAC960_Device_Dead + DAC960_Critical("Physical Device %d:%d is now %s\n", Controller, + Controller->V1.DeviceStateChannel, + Controller->V1.DeviceStateTargetID, + (NewDeviceState->DeviceState + == DAC960_V1_Device_Dead ? "DEAD" : NewDeviceState->DeviceState - == DAC960_Device_WriteOnly + == DAC960_V1_Device_WriteOnly ? "WRITE-ONLY" : NewDeviceState->DeviceState - == DAC960_Device_Online + == DAC960_V1_Device_Online ? "ONLINE" : "STANDBY")); - if (OldDeviceState->DeviceState == DAC960_Device_Dead && - NewDeviceState->DeviceState != DAC960_Device_Dead) + if (OldDeviceState->DeviceState == DAC960_V1_Device_Dead && + NewDeviceState->DeviceState != DAC960_V1_Device_Dead) { - Controller->NeedDeviceInquiryInformation = true; - Controller->NeedDeviceSerialNumberInformation = true; + Controller->V1.NeedDeviceInquiryInformation = true; + Controller->V1.NeedDeviceSerialNumberInformation = true; } + memcpy(OldDeviceState, NewDeviceState, + sizeof(DAC960_V1_DeviceState_T)); } - else if (CommandOpcode == DAC960_GetLogicalDriveInformation) + else if (CommandOpcode == DAC960_V1_GetLogicalDriveInformation) { int LogicalDriveNumber; for (LogicalDriveNumber = 0; LogicalDriveNumber < Controller->LogicalDriveCount; LogicalDriveNumber++) { - DAC960_LogicalDriveInformation_T *OldLogicalDriveInformation = - &Controller->LogicalDriveInformation - [Controller->LogicalDriveInformationIndex] - [LogicalDriveNumber]; - DAC960_LogicalDriveInformation_T *NewLogicalDriveInformation = - &Controller->LogicalDriveInformation - [Controller->LogicalDriveInformationIndex ^ 1] - [LogicalDriveNumber]; + DAC960_V1_LogicalDriveInformation_T *OldLogicalDriveInformation = + &Controller->V1.LogicalDriveInformation[LogicalDriveNumber]; + DAC960_V1_LogicalDriveInformation_T *NewLogicalDriveInformation = + &Controller->V1.NewLogicalDriveInformation[LogicalDriveNumber]; if (NewLogicalDriveInformation->LogicalDriveState != OldLogicalDriveInformation->LogicalDriveState) DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) " @@ -2181,11 +3314,11 @@ Controller->ControllerNumber, LogicalDriveNumber, (NewLogicalDriveInformation->LogicalDriveState - == DAC960_LogicalDrive_Online + == DAC960_V1_LogicalDrive_Online ? "ONLINE" : NewLogicalDriveInformation->LogicalDriveState - == DAC960_LogicalDrive_Critical - ? "CRITICAL" : "OFFLINE")); + == DAC960_V1_LogicalDrive_Critical + ? "CRITICAL" : "OFFLINE")); if (NewLogicalDriveInformation->WriteBack != OldLogicalDriveInformation->WriteBack) DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) " @@ -2196,22 +3329,24 @@ (NewLogicalDriveInformation->WriteBack ? "WRITE BACK" : "WRITE THRU")); } - Controller->LogicalDriveInformationIndex ^= 1; + memcpy(&Controller->V1.LogicalDriveInformation, + &Controller->V1.NewLogicalDriveInformation, + sizeof(DAC960_V1_LogicalDriveInformationArray_T)); } - else if (CommandOpcode == DAC960_GetRebuildProgress) + else if (CommandOpcode == DAC960_V1_GetRebuildProgress) { unsigned int LogicalDriveNumber = - Controller->RebuildProgress.LogicalDriveNumber; + Controller->V1.RebuildProgress.LogicalDriveNumber; unsigned int LogicalDriveSize = - Controller->RebuildProgress.LogicalDriveSize; + Controller->V1.RebuildProgress.LogicalDriveSize; unsigned int BlocksCompleted = - LogicalDriveSize - Controller->RebuildProgress.RemainingBlocks; - if (CommandStatus == DAC960_NoRebuildOrCheckInProgress && - Controller->LastRebuildStatus == DAC960_NormalCompletion) - CommandStatus = DAC960_RebuildSuccessful; + LogicalDriveSize - Controller->V1.RebuildProgress.RemainingBlocks; + if (CommandStatus == DAC960_V1_NoRebuildOrCheckInProgress && + Controller->V1.LastRebuildStatus == DAC960_V1_NormalCompletion) + CommandStatus = DAC960_V1_RebuildSuccessful; switch (CommandStatus) { - case DAC960_NormalCompletion: + case DAC960_V1_NormalCompletion: Controller->EphemeralProgressMessage = true; DAC960_Progress("Rebuild in Progress: " "Logical Drive %d (/dev/rd/c%dd%d) " @@ -2223,244 +3358,1061 @@ / (LogicalDriveSize >> 7)); Controller->EphemeralProgressMessage = false; break; - case DAC960_RebuildFailed_LogicalDriveFailure: + case DAC960_V1_RebuildFailed_LogicalDriveFailure: DAC960_Progress("Rebuild Failed due to " "Logical Drive Failure\n", Controller); break; - case DAC960_RebuildFailed_BadBlocksOnOther: + case DAC960_V1_RebuildFailed_BadBlocksOnOther: DAC960_Progress("Rebuild Failed due to " "Bad Blocks on Other Drives\n", Controller); break; - case DAC960_RebuildFailed_NewDriveFailed: + case DAC960_V1_RebuildFailed_NewDriveFailed: DAC960_Progress("Rebuild Failed due to " "Failure of Drive Being Rebuilt\n", Controller); break; - case DAC960_NoRebuildOrCheckInProgress: + case DAC960_V1_NoRebuildOrCheckInProgress: break; - case DAC960_RebuildSuccessful: + case DAC960_V1_RebuildSuccessful: DAC960_Progress("Rebuild Completed Successfully\n", Controller); break; - case DAC960_RebuildSuccessfullyTerminated: + case DAC960_V1_RebuildSuccessfullyTerminated: DAC960_Progress("Rebuild Successfully Terminated\n", Controller); break; } - Controller->LastRebuildStatus = CommandStatus; + Controller->V1.LastRebuildStatus = CommandStatus; if (CommandType != DAC960_MonitoringCommand && - Controller->RebuildStatusPending) + Controller->V1.RebuildStatusPending) { - Command->CommandStatus = Controller->PendingRebuildStatus; - Controller->RebuildStatusPending = false; + Command->V1.CommandStatus = Controller->V1.PendingRebuildStatus; + Controller->V1.RebuildStatusPending = false; } else if (CommandType == DAC960_MonitoringCommand && - CommandStatus != DAC960_NormalCompletion && - CommandStatus != DAC960_NoRebuildOrCheckInProgress) + CommandStatus != DAC960_V1_NormalCompletion && + CommandStatus != DAC960_V1_NoRebuildOrCheckInProgress) + { + Controller->V1.PendingRebuildStatus = CommandStatus; + Controller->V1.RebuildStatusPending = true; + } + } + else if (CommandOpcode == DAC960_V1_RebuildStat) + { + unsigned int LogicalDriveNumber = + Controller->V1.RebuildProgress.LogicalDriveNumber; + unsigned int LogicalDriveSize = + Controller->V1.RebuildProgress.LogicalDriveSize; + unsigned int BlocksCompleted = + LogicalDriveSize - Controller->V1.RebuildProgress.RemainingBlocks; + if (CommandStatus == DAC960_V1_NormalCompletion) + { + Controller->EphemeralProgressMessage = true; + DAC960_Progress("Consistency Check in Progress: " + "Logical Drive %d (/dev/rd/c%dd%d) " + "%d%% completed\n", + Controller, LogicalDriveNumber, + Controller->ControllerNumber, + LogicalDriveNumber, + (100 * (BlocksCompleted >> 7)) + / (LogicalDriveSize >> 7)); + Controller->EphemeralProgressMessage = false; + } + } + } + if (CommandType == DAC960_MonitoringCommand) + { + if (Controller->V1.NewEventLogSequenceNumber + - Controller->V1.OldEventLogSequenceNumber > 0) + { + Command->V1.CommandMailbox.Type3E.CommandOpcode = + DAC960_V1_PerformEventLogOperation; + Command->V1.CommandMailbox.Type3E.OperationType = + DAC960_V1_GetEventLogEntry; + Command->V1.CommandMailbox.Type3E.OperationQualifier = 1; + Command->V1.CommandMailbox.Type3E.SequenceNumber = + Controller->V1.OldEventLogSequenceNumber; + Command->V1.CommandMailbox.Type3E.BusAddress = + Virtual_to_Bus(&Controller->V1.EventLogEntry); + DAC960_QueueCommand(Command); + return; + } + if (Controller->V1.NeedErrorTableInformation) + { + Controller->V1.NeedErrorTableInformation = false; + Command->V1.CommandMailbox.Type3.CommandOpcode = + DAC960_V1_GetErrorTable; + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(&Controller->V1.NewErrorTable); + DAC960_QueueCommand(Command); + return; + } + if (Controller->V1.NeedRebuildProgress && + Controller->V1.RebuildProgressFirst) + { + Controller->V1.NeedRebuildProgress = false; + Command->V1.CommandMailbox.Type3.CommandOpcode = + DAC960_V1_GetRebuildProgress; + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(&Controller->V1.RebuildProgress); + DAC960_QueueCommand(Command); + return; + } + if (Controller->V1.NeedDeviceStateInformation) + { + if (Controller->V1.NeedDeviceInquiryInformation) + { + DAC960_V1_DCDB_T *DCDB = &Controller->V1.MonitoringDCDB; + DAC960_SCSI_Inquiry_T *InquiryStandardData = + &Controller->V1.InquiryStandardData + [Controller->V1.DeviceStateChannel] + [Controller->V1.DeviceStateTargetID]; + InquiryStandardData->PeripheralDeviceType = 0x1F; + Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB; + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(DCDB); + DCDB->Channel = Controller->V1.DeviceStateChannel; + DCDB->TargetID = Controller->V1.DeviceStateTargetID; + DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem; + DCDB->EarlyStatus = false; + DCDB->Timeout = DAC960_V1_DCDB_Timeout_10_seconds; + DCDB->NoAutomaticRequestSense = false; + DCDB->DisconnectPermitted = true; + DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_T); + DCDB->BusAddress = Virtual_to_Bus(InquiryStandardData); + DCDB->CDBLength = 6; + DCDB->TransferLengthHigh4 = 0; + DCDB->SenseLength = sizeof(DCDB->SenseData); + DCDB->CDB[0] = 0x12; /* INQUIRY */ + DCDB->CDB[1] = 0; /* EVPD = 0 */ + DCDB->CDB[2] = 0; /* Page Code */ + DCDB->CDB[3] = 0; /* Reserved */ + DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_T); + DCDB->CDB[5] = 0; /* Control */ + DAC960_QueueCommand(Command); + Controller->V1.NeedDeviceInquiryInformation = false; + return; + } + if (Controller->V1.NeedDeviceSerialNumberInformation) + { + DAC960_V1_DCDB_T *DCDB = &Controller->V1.MonitoringDCDB; + DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber = + &Controller->V1.InquiryUnitSerialNumber + [Controller->V1.DeviceStateChannel] + [Controller->V1.DeviceStateTargetID]; + InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; + Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB; + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(DCDB); + DCDB->Channel = Controller->V1.DeviceStateChannel; + DCDB->TargetID = Controller->V1.DeviceStateTargetID; + DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem; + DCDB->EarlyStatus = false; + DCDB->Timeout = DAC960_V1_DCDB_Timeout_10_seconds; + DCDB->NoAutomaticRequestSense = false; + DCDB->DisconnectPermitted = true; + DCDB->TransferLength = + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); + DCDB->BusAddress = Virtual_to_Bus(InquiryUnitSerialNumber); + DCDB->CDBLength = 6; + DCDB->TransferLengthHigh4 = 0; + DCDB->SenseLength = sizeof(DCDB->SenseData); + DCDB->CDB[0] = 0x12; /* INQUIRY */ + DCDB->CDB[1] = 1; /* EVPD = 1 */ + DCDB->CDB[2] = 0x80; /* Page Code */ + DCDB->CDB[3] = 0; /* Reserved */ + DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); + DCDB->CDB[5] = 0; /* Control */ + DAC960_QueueCommand(Command); + Controller->V1.NeedDeviceSerialNumberInformation = false; + return; + } + if (++Controller->V1.DeviceStateTargetID == Controller->Targets) + { + Controller->V1.DeviceStateChannel++; + Controller->V1.DeviceStateTargetID = 0; + } + while (Controller->V1.DeviceStateChannel < Controller->Channels) + { + DAC960_V1_DeviceState_T *OldDeviceState = + &Controller->V1.DeviceState[Controller->V1.DeviceStateChannel] + [Controller->V1.DeviceStateTargetID]; + if (OldDeviceState->Present && + OldDeviceState->DeviceType == DAC960_V1_DiskType) + { + Command->V1.CommandMailbox.Type3D.CommandOpcode = + DAC960_V1_GetDeviceState; + Command->V1.CommandMailbox.Type3D.Channel = + Controller->V1.DeviceStateChannel; + Command->V1.CommandMailbox.Type3D.TargetID = + Controller->V1.DeviceStateTargetID; + Command->V1.CommandMailbox.Type3D.BusAddress = + Virtual_to_Bus(&Controller->V1.NewDeviceState); + DAC960_QueueCommand(Command); + return; + } + if (++Controller->V1.DeviceStateTargetID == Controller->Targets) + { + Controller->V1.DeviceStateChannel++; + Controller->V1.DeviceStateTargetID = 0; + } + } + Controller->V1.NeedDeviceStateInformation = false; + } + if (Controller->V1.NeedLogicalDriveInformation) + { + Controller->V1.NeedLogicalDriveInformation = false; + Command->V1.CommandMailbox.Type3.CommandOpcode = + DAC960_V1_GetLogicalDriveInformation; + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(&Controller->V1.NewLogicalDriveInformation); + DAC960_QueueCommand(Command); + return; + } + if (Controller->V1.NeedRebuildProgress) + { + Controller->V1.NeedRebuildProgress = false; + Command->V1.CommandMailbox.Type3.CommandOpcode = + DAC960_V1_GetRebuildProgress; + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(&Controller->V1.RebuildProgress); + DAC960_QueueCommand(Command); + return; + } + if (Controller->V1.NeedConsistencyCheckProgress) + { + Controller->V1.NeedConsistencyCheckProgress = false; + Command->V1.CommandMailbox.Type3.CommandOpcode = + DAC960_V1_RebuildStat; + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(&Controller->V1.RebuildProgress); + DAC960_QueueCommand(Command); + return; + } + Controller->MonitoringTimerCount++; + Controller->MonitoringTimer.expires = + jiffies + DAC960_MonitoringTimerInterval; + add_timer(&Controller->MonitoringTimer); + } + if (CommandType == DAC960_ImmediateCommand) + { + up(Command->Semaphore); + Command->Semaphore = NULL; + return; + } + if (CommandType == DAC960_QueuedCommand) + { + DAC960_V1_KernelCommand_T *KernelCommand = Command->V1.KernelCommand; + KernelCommand->CommandStatus = Command->V1.CommandStatus; + Command->V1.KernelCommand = NULL; + if (CommandOpcode == DAC960_V1_DCDB) + Controller->V1.DirectCommandActive[KernelCommand->DCDB->Channel] + [KernelCommand->DCDB->TargetID] = + false; + DAC960_DeallocateCommand(Command); + KernelCommand->CompletionFunction(KernelCommand); + return; + } + /* + Queue a Status Monitoring Command to the Controller using the just + completed Command if one was deferred previously due to lack of a + free Command when the Monitoring Timer Function was called. + */ + if (Controller->MonitoringCommandDeferred) + { + Controller->MonitoringCommandDeferred = false; + DAC960_V1_QueueMonitoringCommand(Command); + return; + } + /* + Deallocate the Command. + */ + DAC960_DeallocateCommand(Command); + /* + Wake up any processes waiting on a free Command. + */ + wake_up(&Controller->CommandWaitQueue); +} + + +/* + DAC960_V2_ReadWriteError prints an appropriate error message for Command + when an error occurs on a Read or Write operation. +*/ + +static void DAC960_V2_ReadWriteError(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + unsigned char *SenseErrors[] = { "NO SENSE", "RECOVERED ERROR", + "NOT READY", "MEDIUM ERROR", + "HARDWARE ERROR", "ILLEGAL REQUEST", + "UNIT ATTENTION", "DATA PROTECT", + "BLANK CHECK", "VENDOR-SPECIFIC", + "COPY ABORTED", "ABORTED COMMAND", + "EQUAL", "VOLUME OVERFLOW", + "MISCOMPARE", "RESERVED" }; + unsigned char *CommandName = "UNKNOWN"; + switch (Command->CommandType) + { + case DAC960_ReadCommand: + case DAC960_ReadRetryCommand: + CommandName = "READ"; + break; + case DAC960_WriteCommand: + case DAC960_WriteRetryCommand: + CommandName = "WRITE"; + break; + case DAC960_MonitoringCommand: + case DAC960_ImmediateCommand: + case DAC960_QueuedCommand: + break; + } + DAC960_Error("Error Condition %s on %s:\n", Controller, + SenseErrors[Command->V2.RequestSense.SenseKey], CommandName); + DAC960_Error(" /dev/rd/c%dd%d: absolute blocks %d..%d\n", + Controller, Controller->ControllerNumber, + Command->LogicalDriveNumber, Command->BlockNumber, + Command->BlockNumber + Command->BlockCount - 1); + if (DAC960_PartitionNumber(Command->BufferHeader->b_rdev) > 0) + DAC960_Error(" /dev/rd/c%dd%dp%d: relative blocks %d..%d\n", + Controller, Controller->ControllerNumber, + Command->LogicalDriveNumber, + DAC960_PartitionNumber(Command->BufferHeader->b_rdev), + Command->BufferHeader->b_rsector, + Command->BufferHeader->b_rsector + Command->BlockCount - 1); +} + + +/* + DAC960_V2_ReportEvent prints an appropriate message when a Controller Event + occurs. +*/ + +static void DAC960_V2_ReportEvent(DAC960_Controller_T *Controller, + DAC960_V2_Event_T *Event) +{ + DAC960_SCSI_RequestSense_T *RequestSense = + (DAC960_SCSI_RequestSense_T *) &Event->RequestSenseData; + unsigned char MessageBuffer[DAC960_LineBufferSize]; + static struct { int EventCode; unsigned char *EventMessage; } EventList[] = + { /* Physical Device Events (0x0000 - 0x007F) */ + { 0x0001, "P Online" }, + { 0x0002, "P Standby" }, + { 0x0005, "P Automatic Rebuild Started" }, + { 0x0006, "P Manual Rebuild Started" }, + { 0x0007, "P Rebuild Completed" }, + { 0x0008, "P Rebuild Cancelled" }, + { 0x0009, "P Rebuild Failed for Unknown Reasons" }, + { 0x000A, "P Rebuild Failed due to New Physical Device" }, + { 0x000B, "P Rebuild Failed due to Logical Drive Failure" }, + { 0x000C, "S Offline" }, + { 0x000D, "P Found" }, + { 0x000E, "P Gone" }, + { 0x000F, "P Unconfigured" }, + { 0x0010, "P Expand Capacity Started" }, + { 0x0011, "P Expand Capacity Completed" }, + { 0x0012, "P Expand Capacity Failed" }, + { 0x0016, "P Parity Error" }, + { 0x0017, "P Soft Error" }, + { 0x0018, "P Miscellaneous Error" }, + { 0x0019, "P Reset" }, + { 0x001A, "P Active Spare Found" }, + { 0x001B, "P Warm Spare Found" }, + { 0x001C, "S Sense Data Received" }, + { 0x001D, "P Initialization Started" }, + { 0x001E, "P Initialization Completed" }, + { 0x001F, "P Initialization Failed" }, + { 0x0020, "P Initialization Cancelled" }, + { 0x0021, "P Failed because Write Recovery Failed" }, + { 0x0022, "P Failed because SCSI Bus Reset Failed" }, + { 0x0023, "P Failed because of Double Check Condition" }, + { 0x0024, "P Failed because Device Cannot Be Accessed" }, + { 0x0025, "P Failed because of Gross Error on SCSI Processor" }, + { 0x0026, "P Failed because of Bad Tag from Device" }, + { 0x0027, "P Failed because of Command Timeout" }, + { 0x0028, "P Failed because of System Reset" }, + { 0x0029, "P Failed because of Busy Status or Parity Error" }, + { 0x002A, "P Failed because Host Set Device to Failed State" }, + { 0x002B, "P Failed because of Selection Timeout" }, + { 0x002C, "P Failed because of SCSI Bus Phase Error" }, + { 0x002D, "P Failed because Device Returned Unknown Status" }, + { 0x002E, "P Failed because Device Not Ready" }, + { 0x002F, "P Failed because Device Not Found at Startup" }, + { 0x0030, "P Failed because COD Write Operation Failed" }, + { 0x0031, "P Failed because BDT Write Operation Failed" }, + { 0x0039, "P Missing at Startup" }, + { 0x003A, "P Start Rebuild Failed due to Physical Drive Too Small" }, + /* Logical Device Events (0x0080 - 0x00FF) */ + { 0x0080, "M Consistency Check Started" }, + { 0x0081, "M Consistency Check Completed" }, + { 0x0082, "M Consistency Check Cancelled" }, + { 0x0083, "M Consistency Check Completed With Errors" }, + { 0x0084, "M Consistency Check Failed due to Logical Drive Failure" }, + { 0x0085, "M Consistency Check Failed due to Physical Device Failure" }, + { 0x0086, "L Offline" }, + { 0x0087, "L Critical" }, + { 0x0088, "L Online" }, + { 0x0089, "M Automatic Rebuild Started" }, + { 0x008A, "M Manual Rebuild Started" }, + { 0x008B, "M Rebuild Completed" }, + { 0x008C, "M Rebuild Cancelled" }, + { 0x008D, "M Rebuild Failed for Unknown Reasons" }, + { 0x008E, "M Rebuild Failed due to New Physical Device" }, + { 0x008F, "M Rebuild Failed due to Logical Drive Failure" }, + { 0x0090, "L Initialization Started" }, + { 0x0091, "L Initialization Completed" }, + { 0x0092, "L Initialization Cancelled" }, + { 0x0093, "L Initialization Failed" }, + { 0x0094, "L Found" }, + { 0x0095, "L Gone" }, + { 0x0096, "L Expand Capacity Started" }, + { 0x0097, "L Expand Capacity Completed" }, + { 0x0098, "L Expand Capacity Failed" }, + { 0x0099, "L Bad Block Found" }, + { 0x009A, "L Size Changed" }, + { 0x009B, "L Type Changed" }, + { 0x009C, "L Bad Data Block Found" }, + { 0x009E, "L Read of Data Block in BDT" }, + { 0x009F, "L Write Back Data for Disk Block Lost" }, + /* Fault Management Events (0x0100 - 0x017F) */ + { 0x0140, "E Fan %d Failed" }, + { 0x0141, "E Fan %d OK" }, + { 0x0142, "E Fan %d Not Present" }, + { 0x0143, "E Power Supply %d Failed" }, + { 0x0144, "E Power Supply %d OK" }, + { 0x0145, "E Power Supply %d Not Present" }, + { 0x0146, "E Temperature Sensor %d Failed" }, + { 0x0147, "E Temperature Sensor %d Critical" }, + { 0x0148, "E Temperature Sensor %d OK" }, + { 0x0149, "E Temperature Sensor %d Not Present" }, + { 0x014A, "E Unit %d Access Critical" }, + { 0x014B, "E Unit %d Access OK" }, + { 0x014C, "E Unit %d Access Offline" }, + /* Controller Events (0x0180 - 0x01FF) */ + { 0x0181, "C Cache Write Back Error" }, + { 0x0188, "C Battery Backup Unit Found" }, + { 0x0189, "C Battery Backup Unit Charge Level Low" }, + { 0x018A, "C Battery Backup Unit Charge Level OK" }, + { 0x0193, "C Installation Aborted" }, + { 0x0195, "C Mirror Race Recovery In Progress" }, + { 0x0196, "C Mirror Race on Critical Drive" }, + { 0x019E, "C Memory Soft ECC Error" }, + { 0x019F, "C Memory Hard ECC Error" }, + { 0x01A2, "C Battery Backup Unit Failed" }, + { 0, "" } }; + int EventListIndex = 0, EventCode; + unsigned char EventType, *EventMessage; + while (true) + { + EventCode = EventList[EventListIndex].EventCode; + if (EventCode == Event->EventCode || EventCode == 0) break; + EventListIndex++; + } + EventType = EventList[EventListIndex].EventMessage[0]; + EventMessage = &EventList[EventListIndex].EventMessage[2]; + if (EventCode == 0) + { + DAC960_Critical("Unknown Controller Event Code %04X\n", + Controller, Event->EventCode); + return; + } + switch (EventType) + { + case 'P': + DAC960_Critical("Physical Device %d:%d %s\n", Controller, + Event->Channel, Event->TargetID, EventMessage); + break; + case 'L': + DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) %s\n", Controller, + Event->LogicalUnit, Controller->ControllerNumber, + Event->LogicalUnit, EventMessage); + break; + case 'M': + DAC960_Progress("Logical Drive %d (/dev/rd/c%dd%d) %s\n", Controller, + Event->LogicalUnit, Controller->ControllerNumber, + Event->LogicalUnit, EventMessage); + break; + case 'S': + if (RequestSense->SenseKey == DAC960_SenseKey_NoSense || + (RequestSense->SenseKey == DAC960_SenseKey_NotReady && + RequestSense->AdditionalSenseCode == 0x04 && + (RequestSense->AdditionalSenseCodeQualifier == 0x01 || + RequestSense->AdditionalSenseCodeQualifier == 0x02))) + break; + DAC960_Critical("Physical Device %d:%d %s\n", Controller, + Event->Channel, Event->TargetID, EventMessage); + DAC960_Critical("Physical Device %d:%d Request Sense: " + "Sense Key = %d, ASC = %02X, ASCQ = %02X\n", + Controller, + Event->Channel, + Event->TargetID, + RequestSense->SenseKey, + RequestSense->AdditionalSenseCode, + RequestSense->AdditionalSenseCodeQualifier); + DAC960_Critical("Physical Device %d:%d Request Sense: " + "Information = %02X%02X%02X%02X " + "%02X%02X%02X%02X\n", + Controller, + Event->Channel, + Event->TargetID, + RequestSense->Information[0], + RequestSense->Information[1], + RequestSense->Information[2], + RequestSense->Information[3], + RequestSense->CommandSpecificInformation[0], + RequestSense->CommandSpecificInformation[1], + RequestSense->CommandSpecificInformation[2], + RequestSense->CommandSpecificInformation[3]); + break; + case 'E': + sprintf(MessageBuffer, EventMessage, Event->LogicalUnit); + DAC960_Critical("Enclosure %d %s\n", Controller, + Event->TargetID, MessageBuffer); + break; + case 'C': + DAC960_Critical("Controller %s\n", Controller, EventMessage); + break; + default: + DAC960_Critical("Unknown Controller Event Code %04X\n", + Controller, Event->EventCode); + break; + } +} + + +/* + DAC960_V2_ReportProgress prints an appropriate progress message for + Logical Device Long Operations. +*/ + +static void DAC960_V2_ReportProgress(DAC960_Controller_T *Controller, + unsigned char *MessageString, + unsigned int LogicalDeviceNumber, + unsigned long BlocksCompleted, + unsigned long LogicalDeviceSize) +{ + Controller->EphemeralProgressMessage = true; + DAC960_Progress("%s in Progress: Logical Drive %d (/dev/rd/c%dd%d) " + "%d%% completed\n", Controller, + MessageString, + LogicalDeviceNumber, + Controller->ControllerNumber, + LogicalDeviceNumber, + (100 * (BlocksCompleted >> 7)) / (LogicalDeviceSize >> 7)); + Controller->EphemeralProgressMessage = false; +} + + +/* + DAC960_V2_ProcessCompletedCommand performs completion processing for Command + for DAC960 V2 Firmware Controllers. +*/ + +static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + DAC960_CommandType_T CommandType = Command->CommandType; + DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_IOCTL_Opcode_T CommandOpcode = CommandMailbox->Common.IOCTL_Opcode; + DAC960_V2_CommandStatus_T CommandStatus = Command->V2.CommandStatus; + BufferHeader_T *BufferHeader = Command->BufferHeader; + if (CommandType == DAC960_ReadCommand || + CommandType == DAC960_WriteCommand) + { + if (CommandStatus == DAC960_V2_NormalCompletion) + { + /* + Perform completion processing for all buffers in this I/O Request. + */ + while (BufferHeader != NULL) + { + BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext; + BufferHeader->b_reqnext = NULL; + DAC960_ProcessCompletedBuffer(BufferHeader, true); + BufferHeader = NextBufferHeader; + } + /* + Wake up requestor for swap file paging requests. + */ + if (Command->Semaphore != NULL) { - Controller->PendingRebuildStatus = CommandStatus; - Controller->RebuildStatusPending = true; + up(Command->Semaphore); + Command->Semaphore = NULL; } + add_blkdev_randomness(DAC960_MAJOR + Controller->ControllerNumber); + } + else if (Command->V2.RequestSense.SenseKey + == DAC960_SenseKey_MediumError && + BufferHeader != NULL && + BufferHeader->b_reqnext != NULL) + { + if (CommandType == DAC960_ReadCommand) + Command->CommandType = DAC960_ReadRetryCommand; + else Command->CommandType = DAC960_WriteRetryCommand; + Command->BlockCount = BufferHeader->b_size >> DAC960_BlockSizeBits; + CommandMailbox->SCSI_10.CommandControlBits + .AdditionalScatterGatherListMemory = false; + CommandMailbox->SCSI_10.DataTransferSize = + Command->BlockCount << DAC960_BlockSizeBits; + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0].SegmentDataPointer = + Virtual_to_Bus(BufferHeader->b_data); + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0].SegmentByteCount = + CommandMailbox->SCSI_10.DataTransferSize; + CommandMailbox->SCSI_10.SCSI_CDB[7] = Command->BlockCount >> 8; + CommandMailbox->SCSI_10.SCSI_CDB[8] = Command->BlockCount; + DAC960_QueueCommand(Command); + return; } - else if (CommandOpcode == DAC960_RebuildStat) + else { - unsigned int LogicalDriveNumber = - Controller->RebuildProgress.LogicalDriveNumber; - unsigned int LogicalDriveSize = - Controller->RebuildProgress.LogicalDriveSize; - unsigned int BlocksCompleted = - LogicalDriveSize - Controller->RebuildProgress.RemainingBlocks; - if (CommandStatus == DAC960_NormalCompletion) + if (Command->V2.RequestSense.SenseKey != DAC960_SenseKey_NotReady) + DAC960_V2_ReadWriteError(Command); + /* + Perform completion processing for all buffers in this I/O Request. + */ + while (BufferHeader != NULL) { - Controller->EphemeralProgressMessage = true; - DAC960_Progress("Consistency Check in Progress: " - "Logical Drive %d (/dev/rd/c%dd%d) " - "%d%% completed\n", - Controller, LogicalDriveNumber, - Controller->ControllerNumber, - LogicalDriveNumber, - (100 * (BlocksCompleted >> 7)) - / (LogicalDriveSize >> 7)); - Controller->EphemeralProgressMessage = false; + BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext; + BufferHeader->b_reqnext = NULL; + DAC960_ProcessCompletedBuffer(BufferHeader, false); + BufferHeader = NextBufferHeader; + } + /* + Wake up requestor for swap file paging requests. + */ + if (Command->Semaphore != NULL) + { + up(Command->Semaphore); + Command->Semaphore = NULL; } } } - if (CommandType == DAC960_MonitoringCommand) + else if (CommandType == DAC960_ReadRetryCommand || + CommandType == DAC960_WriteRetryCommand) { - if (Controller->NewEventLogSequenceNumber - - Controller->OldEventLogSequenceNumber > 0) + BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext; + BufferHeader->b_reqnext = NULL; + /* + Perform completion processing for this single buffer. + */ + if (CommandStatus == DAC960_V2_NormalCompletion) + DAC960_ProcessCompletedBuffer(BufferHeader, true); + else { - Command->CommandMailbox.Type3E.CommandOpcode = - DAC960_PerformEventLogOperation; - Command->CommandMailbox.Type3E.OperationType = - DAC960_GetEventLogEntry; - Command->CommandMailbox.Type3E.OperationQualifier = 1; - Command->CommandMailbox.Type3E.SequenceNumber = - Controller->OldEventLogSequenceNumber; - Command->CommandMailbox.Type3E.BusAddress = - Virtual_to_Bus(&Controller->EventLogEntry); - DAC960_QueueCommand(Command); - return; + if (Command->V2.RequestSense.SenseKey != DAC960_SenseKey_NotReady) + DAC960_V2_ReadWriteError(Command); + DAC960_ProcessCompletedBuffer(BufferHeader, false); } - if (Controller->NeedErrorTableInformation) + if (NextBufferHeader != NULL) { - Controller->NeedErrorTableInformation = false; - Command->CommandMailbox.Type3.CommandOpcode = DAC960_GetErrorTable; - Command->CommandMailbox.Type3.BusAddress = - Virtual_to_Bus( - &Controller->ErrorTable[Controller->ErrorTableIndex ^ 1]); - DAC960_QueueCommand(Command); - return; - } - if (Controller->NeedRebuildProgress && - Controller->Enquiry[Controller->EnquiryIndex] - .CriticalLogicalDriveCount < - Controller->Enquiry[Controller->EnquiryIndex ^ 1] - .CriticalLogicalDriveCount) - { - Controller->NeedRebuildProgress = false; - Command->CommandMailbox.Type3.CommandOpcode = - DAC960_GetRebuildProgress; - Command->CommandMailbox.Type3.BusAddress = - Virtual_to_Bus(&Controller->RebuildProgress); + Command->BlockNumber += + BufferHeader->b_size >> DAC960_BlockSizeBits; + Command->BlockCount = + NextBufferHeader->b_size >> DAC960_BlockSizeBits; + Command->BufferHeader = NextBufferHeader; + CommandMailbox->SCSI_10.DataTransferSize = + Command->BlockCount << DAC960_BlockSizeBits; + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(NextBufferHeader->b_data); + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->SCSI_10.DataTransferSize; + CommandMailbox->SCSI_10.SCSI_CDB[2] = Command->BlockNumber >> 24; + CommandMailbox->SCSI_10.SCSI_CDB[3] = Command->BlockNumber >> 16; + CommandMailbox->SCSI_10.SCSI_CDB[4] = Command->BlockNumber >> 8; + CommandMailbox->SCSI_10.SCSI_CDB[5] = Command->BlockNumber; + CommandMailbox->SCSI_10.SCSI_CDB[7] = Command->BlockCount >> 8; + CommandMailbox->SCSI_10.SCSI_CDB[8] = Command->BlockCount; DAC960_QueueCommand(Command); return; } - if (Controller->NeedDeviceStateInformation) + } + else if (CommandType == DAC960_MonitoringCommand) + { + if (CommandOpcode == DAC960_V2_GetControllerInfo) { - if (Controller->NeedDeviceInquiryInformation) + DAC960_V2_ControllerInfo_T *NewControllerInfo = + &Controller->V2.NewControllerInformation; + DAC960_V2_ControllerInfo_T *ControllerInfo = + &Controller->V2.ControllerInformation; + Controller->LogicalDriveCount = + NewControllerInfo->LogicalDevicesPresent; + Controller->V2.NeedLogicalDeviceInformation = true; + Controller->V2.NewLogicalDeviceInformation.LogicalDeviceNumber = 0; + Controller->V2.NeedPhysicalDeviceInformation = true; + Controller->V2.PhysicalDeviceIndex = 0; + Controller->V2.NewPhysicalDeviceInformation.Channel = 0; + Controller->V2.NewPhysicalDeviceInformation.TargetID = 0; + Controller->V2.NewPhysicalDeviceInformation.LogicalUnit = 0; + Controller->MonitoringAlertMode = + (NewControllerInfo->LogicalDevicesCritical > 0 || + NewControllerInfo->LogicalDevicesOffline > 0 || + NewControllerInfo->PhysicalDisksCritical > 0 || + NewControllerInfo->PhysicalDisksOffline > 0); + memcpy(ControllerInfo, NewControllerInfo, + sizeof(DAC960_V2_ControllerInfo_T)); + } + else if (CommandOpcode == DAC960_V2_GetEvent) + { + if (CommandStatus == DAC960_V2_NormalCompletion) + DAC960_V2_ReportEvent(Controller, &Controller->V2.Event); + Controller->V2.NextEventSequenceNumber++; + } + else if (CommandOpcode == DAC960_V2_GetPhysicalDeviceInfoValid && + CommandStatus == DAC960_V2_NormalCompletion) + { + DAC960_V2_PhysicalDeviceInfo_T *NewPhysicalDeviceInfo = + &Controller->V2.NewPhysicalDeviceInformation; + unsigned int PhysicalDeviceIndex = Controller->V2.PhysicalDeviceIndex; + DAC960_V2_PhysicalDeviceInfo_T *PhysicalDeviceInfo = + Controller->V2.PhysicalDeviceInformation[PhysicalDeviceIndex]; + DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber; + if (PhysicalDeviceInfo == NULL || + (NewPhysicalDeviceInfo->Channel != + PhysicalDeviceInfo->Channel) || + (NewPhysicalDeviceInfo->TargetID != + PhysicalDeviceInfo->TargetID) || + (NewPhysicalDeviceInfo->LogicalUnit != + PhysicalDeviceInfo->LogicalUnit)) { - DAC960_DCDB_T *DCDB = &Controller->MonitoringDCDB; - DAC960_SCSI_Inquiry_T *InquiryStandardData = - &Controller->InquiryStandardData - [Controller->DeviceStateChannel] - [Controller->DeviceStateTargetID]; - InquiryStandardData->PeripheralDeviceType = 0x1F; - Command->CommandMailbox.Type3.CommandOpcode = DAC960_DCDB; - Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB); - DCDB->Channel = Controller->DeviceStateChannel; - DCDB->TargetID = Controller->DeviceStateTargetID; - DCDB->Direction = DAC960_DCDB_DataTransferDeviceToSystem; - DCDB->EarlyStatus = false; - DCDB->Timeout = DAC960_DCDB_Timeout_10_seconds; - DCDB->NoAutomaticRequestSense = false; - DCDB->DisconnectPermitted = true; - DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_T); - DCDB->BusAddress = Virtual_to_Bus(InquiryStandardData); - DCDB->CDBLength = 6; - DCDB->TransferLengthHigh4 = 0; - DCDB->SenseLength = sizeof(DCDB->SenseData); - DCDB->CDB[0] = 0x12; /* INQUIRY */ - DCDB->CDB[1] = 0; /* EVPD = 0 */ - DCDB->CDB[2] = 0; /* Page Code */ - DCDB->CDB[3] = 0; /* Reserved */ - DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_T); - DCDB->CDB[5] = 0; /* Control */ - DAC960_QueueCommand(Command); - Controller->NeedDeviceInquiryInformation = false; - return; + unsigned int DeviceIndex; + PhysicalDeviceInfo = (DAC960_V2_PhysicalDeviceInfo_T *) + kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T), GFP_ATOMIC); + InquiryUnitSerialNumber = + (DAC960_SCSI_Inquiry_UnitSerialNumber_T *) + kmalloc(sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), + GFP_ATOMIC); + if (InquiryUnitSerialNumber == NULL) + { + kfree(PhysicalDeviceInfo); + PhysicalDeviceInfo = NULL; + } + DAC960_Critical("Physical Device %d:%d Now Exists%s\n", + Controller, + NewPhysicalDeviceInfo->Channel, + NewPhysicalDeviceInfo->TargetID, + (PhysicalDeviceInfo != NULL + ? "" : " - Allocation Failed")); + if (PhysicalDeviceInfo != NULL) + { + for (DeviceIndex = PhysicalDeviceIndex; + DeviceIndex < DAC960_V2_MaxPhysicalDevices - 1; + DeviceIndex++) + { + Controller->V2.PhysicalDeviceInformation[DeviceIndex+1] = + Controller->V2.PhysicalDeviceInformation[DeviceIndex]; + Controller->V2.InquiryUnitSerialNumber[DeviceIndex+1] = + Controller->V2.InquiryUnitSerialNumber[DeviceIndex]; + Controller->V2.PhysicalDeviceInformation + [PhysicalDeviceIndex] = + PhysicalDeviceInfo; + Controller->V2.InquiryUnitSerialNumber + [PhysicalDeviceIndex] = + InquiryUnitSerialNumber; + } + memset(PhysicalDeviceInfo, 0, + sizeof(DAC960_V2_PhysicalDeviceInfo_T)); + PhysicalDeviceInfo->PhysicalDeviceState = + DAC960_V2_Device_InvalidState; + memset(InquiryUnitSerialNumber, 0, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)); + InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; + Controller->V2.NeedDeviceSerialNumberInformation = true; + } } - if (Controller->NeedDeviceSerialNumberInformation) + if (PhysicalDeviceInfo != NULL) { - DAC960_DCDB_T *DCDB = &Controller->MonitoringDCDB; - DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber = - &Controller->InquiryUnitSerialNumber - [Controller->DeviceStateChannel] - [Controller->DeviceStateTargetID]; - InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; - Command->CommandMailbox.Type3.CommandOpcode = DAC960_DCDB; - Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB); - DCDB->Channel = Controller->DeviceStateChannel; - DCDB->TargetID = Controller->DeviceStateTargetID; - DCDB->Direction = DAC960_DCDB_DataTransferDeviceToSystem; - DCDB->EarlyStatus = false; - DCDB->Timeout = DAC960_DCDB_Timeout_10_seconds; - DCDB->NoAutomaticRequestSense = false; - DCDB->DisconnectPermitted = true; - DCDB->TransferLength = - sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); - DCDB->BusAddress = Virtual_to_Bus(InquiryUnitSerialNumber); - DCDB->CDBLength = 6; - DCDB->TransferLengthHigh4 = 0; - DCDB->SenseLength = sizeof(DCDB->SenseData); - DCDB->CDB[0] = 0x12; /* INQUIRY */ - DCDB->CDB[1] = 1; /* EVPD = 1 */ - DCDB->CDB[2] = 0x80; /* Page Code */ - DCDB->CDB[3] = 0; /* Reserved */ - DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); - DCDB->CDB[5] = 0; /* Control */ - DAC960_QueueCommand(Command); - Controller->NeedDeviceSerialNumberInformation = false; - return; + if (NewPhysicalDeviceInfo->PhysicalDeviceState != + PhysicalDeviceInfo->PhysicalDeviceState) + DAC960_Critical("Physical Device %d:%d is now %s\n", Controller, + NewPhysicalDeviceInfo->Channel, + NewPhysicalDeviceInfo->TargetID, + (NewPhysicalDeviceInfo->PhysicalDeviceState + == DAC960_V2_Device_Unconfigured + ? "UNCONFIGURED" + : NewPhysicalDeviceInfo->PhysicalDeviceState + == DAC960_V2_Device_Online + ? "ONLINE" + : NewPhysicalDeviceInfo->PhysicalDeviceState + == DAC960_V2_Device_WriteOnly + ? "WRITE-ONLY" + : NewPhysicalDeviceInfo + ->PhysicalDeviceState + == DAC960_V2_Device_Dead + ? "DEAD" : "STANDBY")); + if ((NewPhysicalDeviceInfo->ParityErrors != + PhysicalDeviceInfo->ParityErrors) || + (NewPhysicalDeviceInfo->SoftErrors != + PhysicalDeviceInfo->SoftErrors) || + (NewPhysicalDeviceInfo->HardErrors != + PhysicalDeviceInfo->HardErrors) || + (NewPhysicalDeviceInfo->MiscellaneousErrors != + PhysicalDeviceInfo->MiscellaneousErrors) || + (NewPhysicalDeviceInfo->CommandTimeouts != + PhysicalDeviceInfo->CommandTimeouts) || + (NewPhysicalDeviceInfo->Retries != + PhysicalDeviceInfo->Retries) || + (NewPhysicalDeviceInfo->Aborts != + PhysicalDeviceInfo->Aborts) || + (NewPhysicalDeviceInfo->PredictedFailuresDetected != + PhysicalDeviceInfo->PredictedFailuresDetected)) + { + DAC960_Critical("Physical Device %d:%d Errors: " + "Parity = %d, Soft = %d, " + "Hard = %d, Misc = %d\n", + Controller, + NewPhysicalDeviceInfo->Channel, + NewPhysicalDeviceInfo->TargetID, + NewPhysicalDeviceInfo->ParityErrors, + NewPhysicalDeviceInfo->SoftErrors, + NewPhysicalDeviceInfo->HardErrors, + NewPhysicalDeviceInfo->MiscellaneousErrors); + DAC960_Critical("Physical Device %d:%d Errors: " + "Timeouts = %d, Retries = %d, " + "Aborts = %d, Predicted = %d\n", + Controller, + NewPhysicalDeviceInfo->Channel, + NewPhysicalDeviceInfo->TargetID, + NewPhysicalDeviceInfo->CommandTimeouts, + NewPhysicalDeviceInfo->Retries, + NewPhysicalDeviceInfo->Aborts, + NewPhysicalDeviceInfo + ->PredictedFailuresDetected); + } + if (PhysicalDeviceInfo->PhysicalDeviceState + == DAC960_V2_Device_Dead && + NewPhysicalDeviceInfo->PhysicalDeviceState + != DAC960_V2_Device_Dead) + Controller->V2.NeedDeviceSerialNumberInformation = true; + memcpy(PhysicalDeviceInfo, NewPhysicalDeviceInfo, + sizeof(DAC960_V2_PhysicalDeviceInfo_T)); } - if (++Controller->DeviceStateTargetID == DAC960_MaxTargets) + NewPhysicalDeviceInfo->LogicalUnit++; + Controller->V2.PhysicalDeviceIndex++; + } + else if (CommandOpcode == DAC960_V2_GetPhysicalDeviceInfoValid) + Controller->V2.NeedPhysicalDeviceInformation = false; + else if (CommandOpcode == DAC960_V2_GetLogicalDeviceInfoValid && + CommandStatus == DAC960_V2_NormalCompletion) + { + DAC960_V2_LogicalDeviceInfo_T *NewLogicalDeviceInfo = + &Controller->V2.NewLogicalDeviceInformation; + unsigned short LogicalDeviceNumber = + NewLogicalDeviceInfo->LogicalDeviceNumber; + DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo = + Controller->V2.LogicalDeviceInformation[LogicalDeviceNumber]; + if (LogicalDeviceInfo == NULL) { - Controller->DeviceStateChannel++; - Controller->DeviceStateTargetID = 0; + DAC960_V2_PhysicalDevice_T PhysicalDevice; + PhysicalDevice.Controller = 0; + PhysicalDevice.Channel = NewLogicalDeviceInfo->Channel; + PhysicalDevice.TargetID = NewLogicalDeviceInfo->TargetID; + PhysicalDevice.LogicalUnit = NewLogicalDeviceInfo->LogicalUnit; + Controller->V2.LogicalDriveToVirtualDevice[LogicalDeviceNumber] = + PhysicalDevice; + LogicalDeviceInfo = (DAC960_V2_LogicalDeviceInfo_T *) + kmalloc(sizeof(DAC960_V2_LogicalDeviceInfo_T), GFP_ATOMIC); + Controller->V2.LogicalDeviceInformation[LogicalDeviceNumber] = + LogicalDeviceInfo; + DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) " + "Now Exists%s\n", Controller, + LogicalDeviceNumber, + Controller->ControllerNumber, + LogicalDeviceNumber, + (LogicalDeviceInfo != NULL + ? "" : " - Allocation Failed")); + if (LogicalDeviceInfo != NULL) + memset(LogicalDeviceInfo, 0, + sizeof(DAC960_V2_LogicalDeviceInfo_T)); } - while (Controller->DeviceStateChannel < Controller->Channels) + if (LogicalDeviceInfo != NULL) { - DAC960_DeviceState_T *OldDeviceState = - &Controller->DeviceState[Controller->DeviceStateIndex] - [Controller->DeviceStateChannel] - [Controller->DeviceStateTargetID]; - if (OldDeviceState->Present && - OldDeviceState->DeviceType == DAC960_DiskType) - { - Command->CommandMailbox.Type3D.CommandOpcode = - DAC960_GetDeviceState; - Command->CommandMailbox.Type3D.Channel = - Controller->DeviceStateChannel; - Command->CommandMailbox.Type3D.TargetID = - Controller->DeviceStateTargetID; - Command->CommandMailbox.Type3D.BusAddress = - Virtual_to_Bus(&Controller->DeviceState - [Controller->DeviceStateIndex ^ 1] - [Controller->DeviceStateChannel] - [Controller->DeviceStateTargetID]); - DAC960_QueueCommand(Command); - return; - } - if (++Controller->DeviceStateTargetID == DAC960_MaxTargets) - { - Controller->DeviceStateChannel++; - Controller->DeviceStateTargetID = 0; - } + unsigned long LogicalDeviceSize = + NewLogicalDeviceInfo->ConfigurableDeviceSizeIn512ByteBlocksOrMB; + if (NewLogicalDeviceInfo->LogicalDeviceState != + LogicalDeviceInfo->LogicalDeviceState) + DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) " + "is now %s\n", Controller, + LogicalDeviceNumber, + Controller->ControllerNumber, + LogicalDeviceNumber, + (NewLogicalDeviceInfo->LogicalDeviceState + == DAC960_V2_LogicalDevice_Online + ? "ONLINE" + : NewLogicalDeviceInfo->LogicalDeviceState + == DAC960_V2_LogicalDevice_Critical + ? "CRITICAL" : "OFFLINE")); + if ((NewLogicalDeviceInfo->SoftErrors != + LogicalDeviceInfo->SoftErrors) || + (NewLogicalDeviceInfo->CommandsFailed != + LogicalDeviceInfo->CommandsFailed) || + (NewLogicalDeviceInfo->DeferredWriteErrors != + LogicalDeviceInfo->DeferredWriteErrors)) + DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) Errors: " + "Soft = %d, Failed = %d, Deferred Write = %d\n", + Controller, LogicalDeviceNumber, + Controller->ControllerNumber, + LogicalDeviceNumber, + NewLogicalDeviceInfo->SoftErrors, + NewLogicalDeviceInfo->CommandsFailed, + NewLogicalDeviceInfo->DeferredWriteErrors); + if (NewLogicalDeviceInfo->ConsistencyCheckInProgress) + DAC960_V2_ReportProgress(Controller, + "Consistency Check", + LogicalDeviceNumber, + NewLogicalDeviceInfo + ->ConsistencyCheckBlockNumber, + LogicalDeviceSize); + else if (NewLogicalDeviceInfo->RebuildInProgress) + DAC960_V2_ReportProgress(Controller, + "Rebuild", + LogicalDeviceNumber, + NewLogicalDeviceInfo + ->RebuildBlockNumber, + LogicalDeviceSize); + else if (NewLogicalDeviceInfo->BackgroundInitializationInProgress) + DAC960_V2_ReportProgress(Controller, + "BackgroundInitialization", + LogicalDeviceNumber, + NewLogicalDeviceInfo + ->BackgroundInitializationBlockNumber, + LogicalDeviceSize); + else if (NewLogicalDeviceInfo->ForegroundInitializationInProgress) + DAC960_V2_ReportProgress(Controller, + "Foreground Initialization", + LogicalDeviceNumber, + NewLogicalDeviceInfo + ->ForegroundInitializationBlockNumber, + LogicalDeviceSize); + else if (NewLogicalDeviceInfo->DataMigrationInProgress) + DAC960_V2_ReportProgress(Controller, + "Data Migration", + LogicalDeviceNumber, + NewLogicalDeviceInfo + ->DataMigrationBlockNumber, + LogicalDeviceSize); + else if (NewLogicalDeviceInfo->PatrolOperationInProgress) + DAC960_V2_ReportProgress(Controller, + "Patrol Operation", + LogicalDeviceNumber, + NewLogicalDeviceInfo + ->PatrolOperationBlockNumber, + LogicalDeviceSize); + memcpy(LogicalDeviceInfo, NewLogicalDeviceInfo, + sizeof(DAC960_V2_LogicalDeviceInfo_T)); } - Controller->NeedDeviceStateInformation = false; - Controller->DeviceStateIndex ^= 1; + NewLogicalDeviceInfo->LogicalDeviceNumber++; } - if (Controller->NeedLogicalDriveInformation) - { - Controller->NeedLogicalDriveInformation = false; - Command->CommandMailbox.Type3.CommandOpcode = - DAC960_GetLogicalDriveInformation; - Command->CommandMailbox.Type3.BusAddress = - Virtual_to_Bus( - &Controller->LogicalDriveInformation - [Controller->LogicalDriveInformationIndex ^ 1]); + else if (CommandOpcode == DAC960_V2_GetLogicalDeviceInfoValid) + Controller->V2.NeedLogicalDeviceInformation = false; + if (Controller->V2.HealthStatusBuffer->NextEventSequenceNumber + - Controller->V2.NextEventSequenceNumber > 0) + { + CommandMailbox->GetEvent.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->GetEvent.DataTransferSize = sizeof(DAC960_V2_Event_T); + CommandMailbox->GetEvent.EventSequenceNumberHigh16 = + Controller->V2.NextEventSequenceNumber >> 16; + CommandMailbox->GetEvent.ControllerNumber = 0; + CommandMailbox->GetEvent.IOCTL_Opcode = + DAC960_V2_GetEvent; + CommandMailbox->GetEvent.EventSequenceNumberLow16 = + Controller->V2.NextEventSequenceNumber & 0xFFFF; + CommandMailbox->GetEvent.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(&Controller->V2.Event); + CommandMailbox->GetEvent.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->GetEvent.DataTransferSize; DAC960_QueueCommand(Command); return; } - if (Controller->NeedRebuildProgress) + if (Controller->V2.NeedPhysicalDeviceInformation) { - Controller->NeedRebuildProgress = false; - Command->CommandMailbox.Type3.CommandOpcode = - DAC960_GetRebuildProgress; - Command->CommandMailbox.Type3.BusAddress = - Virtual_to_Bus(&Controller->RebuildProgress); + if (Controller->V2.NeedDeviceSerialNumberInformation) + { + DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber = + Controller->V2.InquiryUnitSerialNumber + [Controller->V2.PhysicalDeviceIndex - 1]; + InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; + CommandMailbox->SCSI_10.CommandOpcode = + DAC960_V2_SCSI_10_Passthru; + CommandMailbox->SCSI_10.DataTransferSize = + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); + CommandMailbox->SCSI_10.PhysicalDevice.LogicalUnit = + Controller->V2.NewPhysicalDeviceInformation.LogicalUnit - 1; + CommandMailbox->SCSI_10.PhysicalDevice.TargetID = + Controller->V2.NewPhysicalDeviceInformation.TargetID; + CommandMailbox->SCSI_10.PhysicalDevice.Channel = + Controller->V2.NewPhysicalDeviceInformation.Channel; + CommandMailbox->SCSI_10.CDBLength = 6; + CommandMailbox->SCSI_10.SCSI_CDB[0] = 0x12; /* INQUIRY */ + CommandMailbox->SCSI_10.SCSI_CDB[1] = 1; /* EVPD = 1 */ + CommandMailbox->SCSI_10.SCSI_CDB[2] = 0x80; /* Page Code */ + CommandMailbox->SCSI_10.SCSI_CDB[3] = 0; /* Reserved */ + CommandMailbox->SCSI_10.SCSI_CDB[4] = + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); + CommandMailbox->SCSI_10.SCSI_CDB[5] = 0; /* Control */ + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(InquiryUnitSerialNumber); + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->SCSI_10.DataTransferSize; + DAC960_QueueCommand(Command); + Controller->V2.NeedDeviceSerialNumberInformation = false; + return; + } + CommandMailbox->PhysicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->PhysicalDeviceInfo.DataTransferSize = + sizeof(DAC960_V2_PhysicalDeviceInfo_T); + CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.LogicalUnit = + Controller->V2.NewPhysicalDeviceInformation.LogicalUnit; + CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.TargetID = + Controller->V2.NewPhysicalDeviceInformation.TargetID; + CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.Channel = + Controller->V2.NewPhysicalDeviceInformation.Channel; + CommandMailbox->PhysicalDeviceInfo.IOCTL_Opcode = + DAC960_V2_GetPhysicalDeviceInfoValid; + CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(&Controller->V2.NewPhysicalDeviceInformation); + CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->PhysicalDeviceInfo.DataTransferSize; DAC960_QueueCommand(Command); return; } - if (Controller->NeedConsistencyCheckProgress) + if (Controller->V2.NeedLogicalDeviceInformation) { - Controller->NeedConsistencyCheckProgress = false; - Command->CommandMailbox.Type3.CommandOpcode = DAC960_RebuildStat; - Command->CommandMailbox.Type3.BusAddress = - Virtual_to_Bus(&Controller->RebuildProgress); + CommandMailbox->LogicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->LogicalDeviceInfo.DataTransferSize = + sizeof(DAC960_V2_LogicalDeviceInfo_T); + CommandMailbox->LogicalDeviceInfo.LogicalDevice.LogicalDeviceNumber = + Controller->V2.NewLogicalDeviceInformation.LogicalDeviceNumber; + CommandMailbox->LogicalDeviceInfo.IOCTL_Opcode = + DAC960_V2_GetLogicalDeviceInfoValid; + CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(&Controller->V2.NewLogicalDeviceInformation); + CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->LogicalDeviceInfo.DataTransferSize; DAC960_QueueCommand(Command); return; } Controller->MonitoringTimerCount++; Controller->MonitoringTimer.expires = - jiffies + DAC960_MonitoringTimerInterval; + jiffies + DAC960_HealthStatusMonitoringInterval; add_timer(&Controller->MonitoringTimer); } if (CommandType == DAC960_ImmediateCommand) @@ -2471,12 +4423,11 @@ } if (CommandType == DAC960_QueuedCommand) { - DAC960_KernelCommand_T *KernelCommand = Command->KernelCommand; - KernelCommand->CommandStatus = Command->CommandStatus; - Command->KernelCommand = NULL; - if (CommandOpcode == DAC960_DCDB) - Controller->DirectCommandActive[KernelCommand->DCDB->Channel] - [KernelCommand->DCDB->TargetID] = false; + DAC960_V2_KernelCommand_T *KernelCommand = Command->V2.KernelCommand; + KernelCommand->CommandStatus = CommandStatus; + KernelCommand->RequestSenseLength = Command->V2.RequestSenseLength; + KernelCommand->DataTransferLength = Command->V2.DataTransferResidue; + Command->V2.KernelCommand = NULL; DAC960_DeallocateCommand(Command); KernelCommand->CompletionFunction(KernelCommand); return; @@ -2489,7 +4440,7 @@ if (Controller->MonitoringCommandDeferred) { Controller->MonitoringCommandDeferred = false; - DAC960_QueueMonitoringCommand(Command); + DAC960_V2_QueueMonitoringCommand(Command); return; } /* @@ -2504,16 +4455,17 @@ /* - DAC960_InterruptHandler handles hardware interrupts from DAC960 Controllers. + DAC960_BA_InterruptHandler handles hardware interrupts from DAC960 BA Series + Controllers. */ -static void DAC960_InterruptHandler(int IRQ_Channel, - void *DeviceIdentifier, - Registers_T *InterruptRegisters) +static void DAC960_BA_InterruptHandler(int IRQ_Channel, + void *DeviceIdentifier, + Registers_T *InterruptRegisters) { DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; void *ControllerBaseAddress = Controller->BaseAddress; - DAC960_StatusMailbox_T *NextStatusMailbox; + DAC960_V2_StatusMailbox_T *NextStatusMailbox; ProcessorFlags_T ProcessorFlags; /* Acquire exclusive access to Controller. @@ -2522,54 +4474,24 @@ /* Process Hardware Interrupts for Controller. */ - switch (Controller->ControllerType) - { - case DAC960_V5_Controller: - DAC960_V5_AcknowledgeInterrupt(ControllerBaseAddress); - NextStatusMailbox = Controller->NextStatusMailbox; - while (NextStatusMailbox->Fields.Valid) - { - DAC960_CommandIdentifier_T CommandIdentifier = - NextStatusMailbox->Fields.CommandIdentifier; - DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier]; - Command->CommandStatus = NextStatusMailbox->Fields.CommandStatus; - NextStatusMailbox->Word = 0; - if (++NextStatusMailbox > Controller->LastStatusMailbox) - NextStatusMailbox = Controller->FirstStatusMailbox; - DAC960_ProcessCompletedCommand(Command); - } - Controller->NextStatusMailbox = NextStatusMailbox; - break; - case DAC960_V4_Controller: - DAC960_V4_AcknowledgeInterrupt(ControllerBaseAddress); - NextStatusMailbox = Controller->NextStatusMailbox; - while (NextStatusMailbox->Fields.Valid) - { - DAC960_CommandIdentifier_T CommandIdentifier = - NextStatusMailbox->Fields.CommandIdentifier; - DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier]; - Command->CommandStatus = NextStatusMailbox->Fields.CommandStatus; - NextStatusMailbox->Word = 0; - if (++NextStatusMailbox > Controller->LastStatusMailbox) - NextStatusMailbox = Controller->FirstStatusMailbox; - DAC960_ProcessCompletedCommand(Command); - } - Controller->NextStatusMailbox = NextStatusMailbox; - break; - case DAC960_V3_Controller: - while (DAC960_V3_StatusAvailableP(ControllerBaseAddress)) - { - DAC960_CommandIdentifier_T CommandIdentifier = - DAC960_V3_ReadStatusCommandIdentifier(ControllerBaseAddress); - DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier]; - Command->CommandStatus = - DAC960_V3_ReadStatusRegister(ControllerBaseAddress); - DAC960_V3_AcknowledgeInterrupt(ControllerBaseAddress); - DAC960_V3_AcknowledgeStatus(ControllerBaseAddress); - DAC960_ProcessCompletedCommand(Command); - } - break; + DAC960_BA_AcknowledgeInterrupt(ControllerBaseAddress); + NextStatusMailbox = Controller->V2.NextStatusMailbox; + while (NextStatusMailbox->Fields.CommandIdentifier > 0) + { + DAC960_V2_CommandIdentifier_T CommandIdentifier = + NextStatusMailbox->Fields.CommandIdentifier; + DAC960_Command_T *Command = Controller->Commands[CommandIdentifier-1]; + Command->V2.CommandStatus = NextStatusMailbox->Fields.CommandStatus; + Command->V2.RequestSenseLength = + NextStatusMailbox->Fields.RequestSenseLength; + Command->V2.DataTransferResidue = + NextStatusMailbox->Fields.DataTransferResidue; + NextStatusMailbox->Words[0] = 0; + if (++NextStatusMailbox > Controller->V2.LastStatusMailbox) + NextStatusMailbox = Controller->V2.FirstStatusMailbox; + DAC960_V2_ProcessCompletedCommand(Command); } + Controller->V2.NextStatusMailbox = NextStatusMailbox; /* Attempt to remove additional I/O Requests from the Controller's I/O Request Queue and queue them to the Controller. @@ -2583,47 +4505,311 @@ /* - DAC960_QueueMonitoringCommand queues a Monitoring Command to Controller. + DAC960_LP_InterruptHandler handles hardware interrupts from DAC960 LP Series + Controllers. */ -static void DAC960_QueueMonitoringCommand(DAC960_Command_T *Command) +static void DAC960_LP_InterruptHandler(int IRQ_Channel, + void *DeviceIdentifier, + Registers_T *InterruptRegisters) { - DAC960_Controller_T *Controller = Command->Controller; - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; - DAC960_ClearCommand(Command); - Command->CommandType = DAC960_MonitoringCommand; - CommandMailbox->Type3.CommandOpcode = DAC960_Enquiry; - CommandMailbox->Type3.BusAddress = - Virtual_to_Bus(&Controller->Enquiry[Controller->EnquiryIndex ^ 1]); - DAC960_QueueCommand(Command); + DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_V2_StatusMailbox_T *NextStatusMailbox; + ProcessorFlags_T ProcessorFlags; + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags); + /* + Process Hardware Interrupts for Controller. + */ + DAC960_LP_AcknowledgeInterrupt(ControllerBaseAddress); + NextStatusMailbox = Controller->V2.NextStatusMailbox; + while (NextStatusMailbox->Fields.CommandIdentifier > 0) + { + DAC960_V2_CommandIdentifier_T CommandIdentifier = + NextStatusMailbox->Fields.CommandIdentifier; + DAC960_Command_T *Command = Controller->Commands[CommandIdentifier-1]; + Command->V2.CommandStatus = NextStatusMailbox->Fields.CommandStatus; + Command->V2.RequestSenseLength = + NextStatusMailbox->Fields.RequestSenseLength; + Command->V2.DataTransferResidue = + NextStatusMailbox->Fields.DataTransferResidue; + NextStatusMailbox->Words[0] = 0; + if (++NextStatusMailbox > Controller->V2.LastStatusMailbox) + NextStatusMailbox = Controller->V2.FirstStatusMailbox; + DAC960_V2_ProcessCompletedCommand(Command); + } + Controller->V2.NextStatusMailbox = NextStatusMailbox; + /* + Attempt to remove additional I/O Requests from the Controller's + I/O Request Queue and queue them to the Controller. + */ + while (DAC960_ProcessRequest(Controller, false)) ; + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags); } /* - DAC960_MonitoringTimerFunction is the timer function for monitoring - the status of DAC960 Controllers. + DAC960_LA_InterruptHandler handles hardware interrupts from DAC960 LA Series + Controllers. */ -static void DAC960_MonitoringTimerFunction(unsigned long TimerData) +static void DAC960_LA_InterruptHandler(int IRQ_Channel, + void *DeviceIdentifier, + Registers_T *InterruptRegisters) { - DAC960_Controller_T *Controller = (DAC960_Controller_T *) TimerData; - DAC960_Command_T *Command; + DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_V1_StatusMailbox_T *NextStatusMailbox; ProcessorFlags_T ProcessorFlags; /* Acquire exclusive access to Controller. */ - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags); + /* + Process Hardware Interrupts for Controller. + */ + DAC960_LA_AcknowledgeInterrupt(ControllerBaseAddress); + NextStatusMailbox = Controller->V1.NextStatusMailbox; + while (NextStatusMailbox->Fields.Valid) + { + DAC960_V1_CommandIdentifier_T CommandIdentifier = + NextStatusMailbox->Fields.CommandIdentifier; + DAC960_Command_T *Command = Controller->Commands[CommandIdentifier-1]; + Command->V1.CommandStatus = NextStatusMailbox->Fields.CommandStatus; + NextStatusMailbox->Word = 0; + if (++NextStatusMailbox > Controller->V1.LastStatusMailbox) + NextStatusMailbox = Controller->V1.FirstStatusMailbox; + DAC960_V1_ProcessCompletedCommand(Command); + } + Controller->V1.NextStatusMailbox = NextStatusMailbox; /* - Queue a Status Monitoring Command to Controller. + Attempt to remove additional I/O Requests from the Controller's + I/O Request Queue and queue them to the Controller. */ - Command = DAC960_AllocateCommand(Controller); - if (Command != NULL) - DAC960_QueueMonitoringCommand(Command); - else Controller->MonitoringCommandDeferred = true; + while (DAC960_ProcessRequest(Controller, false)) ; /* Release exclusive access to Controller. */ - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags); +} + + +/* + DAC960_PG_InterruptHandler handles hardware interrupts from DAC960 PG Series + Controllers. +*/ + +static void DAC960_PG_InterruptHandler(int IRQ_Channel, + void *DeviceIdentifier, + Registers_T *InterruptRegisters) +{ + DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_V1_StatusMailbox_T *NextStatusMailbox; + ProcessorFlags_T ProcessorFlags; + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags); + /* + Process Hardware Interrupts for Controller. + */ + DAC960_PG_AcknowledgeInterrupt(ControllerBaseAddress); + NextStatusMailbox = Controller->V1.NextStatusMailbox; + while (NextStatusMailbox->Fields.Valid) + { + DAC960_V1_CommandIdentifier_T CommandIdentifier = + NextStatusMailbox->Fields.CommandIdentifier; + DAC960_Command_T *Command = Controller->Commands[CommandIdentifier-1]; + Command->V1.CommandStatus = NextStatusMailbox->Fields.CommandStatus; + NextStatusMailbox->Word = 0; + if (++NextStatusMailbox > Controller->V1.LastStatusMailbox) + NextStatusMailbox = Controller->V1.FirstStatusMailbox; + DAC960_V1_ProcessCompletedCommand(Command); + } + Controller->V1.NextStatusMailbox = NextStatusMailbox; + /* + Attempt to remove additional I/O Requests from the Controller's + I/O Request Queue and queue them to the Controller. + */ + while (DAC960_ProcessRequest(Controller, false)) ; + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags); +} + + +/* + DAC960_PD_InterruptHandler handles hardware interrupts from DAC960 PD Series + Controllers. +*/ + +static void DAC960_PD_InterruptHandler(int IRQ_Channel, + void *DeviceIdentifier, + Registers_T *InterruptRegisters) +{ + DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; + void *ControllerBaseAddress = Controller->BaseAddress; + ProcessorFlags_T ProcessorFlags; + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags); + /* + Process Hardware Interrupts for Controller. + */ + while (DAC960_PD_StatusAvailableP(ControllerBaseAddress)) + { + DAC960_V1_CommandIdentifier_T CommandIdentifier = + DAC960_PD_ReadStatusCommandIdentifier(ControllerBaseAddress); + DAC960_Command_T *Command = Controller->Commands[CommandIdentifier-1]; + Command->V1.CommandStatus = + DAC960_PD_ReadStatusRegister(ControllerBaseAddress); + DAC960_PD_AcknowledgeInterrupt(ControllerBaseAddress); + DAC960_PD_AcknowledgeStatus(ControllerBaseAddress); + DAC960_V1_ProcessCompletedCommand(Command); + } + /* + Attempt to remove additional I/O Requests from the Controller's + I/O Request Queue and queue them to the Controller. + */ + while (DAC960_ProcessRequest(Controller, false)) ; + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags); +} + + +/* + DAC960_V1_QueueMonitoringCommand queues a Monitoring Command to DAC960 V1 + Firmware Controllers. +*/ + +static void DAC960_V1_QueueMonitoringCommand(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + DAC960_V1_ClearCommand(Command); + Command->CommandType = DAC960_MonitoringCommand; + CommandMailbox->Type3.CommandOpcode = DAC960_V1_Enquiry; + CommandMailbox->Type3.BusAddress = Virtual_to_Bus(&Controller->V1.NewEnquiry); + DAC960_QueueCommand(Command); +} + + +/* + DAC960_V2_QueueMonitoringCommand queues a Monitoring Command to DAC960 V2 + Firmware Controllers. +*/ + +static void DAC960_V2_QueueMonitoringCommand(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_ClearCommand(Command); + Command->CommandType = DAC960_MonitoringCommand; + CommandMailbox->ControllerInfo.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->ControllerInfo.CommandControlBits + .DataTransferControllerToHost = true; + CommandMailbox->ControllerInfo.CommandControlBits + .NoAutoRequestSense = true; + CommandMailbox->ControllerInfo.DataTransferSize = + sizeof(DAC960_V2_ControllerInfo_T); + CommandMailbox->ControllerInfo.ControllerNumber = 0; + CommandMailbox->ControllerInfo.IOCTL_Opcode = DAC960_V2_GetControllerInfo; + CommandMailbox->ControllerInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(&Controller->V2.NewControllerInformation); + CommandMailbox->ControllerInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->ControllerInfo.DataTransferSize; + DAC960_QueueCommand(Command); +} + + +/* + DAC960_MonitoringTimerFunction is the timer function for monitoring + the status of DAC960 Controllers. +*/ + +static void DAC960_MonitoringTimerFunction(unsigned long TimerData) +{ + DAC960_Controller_T *Controller = (DAC960_Controller_T *) TimerData; + DAC960_Command_T *Command; + ProcessorFlags_T ProcessorFlags; + if (Controller->FirmwareType == DAC960_V1_Controller) + { + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + /* + Queue a Status Monitoring Command to Controller. + */ + Command = DAC960_AllocateCommand(Controller); + if (Command != NULL) + DAC960_V1_QueueMonitoringCommand(Command); + else Controller->MonitoringCommandDeferred = true; + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + } + else + { + DAC960_V2_ControllerInfo_T *ControllerInfo = + &Controller->V2.ControllerInformation; + unsigned int StatusChangeCounter = + Controller->V2.HealthStatusBuffer->StatusChangeCounter; + if (StatusChangeCounter == Controller->V2.StatusChangeCounter && + Controller->V2.HealthStatusBuffer->NextEventSequenceNumber + == Controller->V2.NextEventSequenceNumber && + (ControllerInfo->BackgroundInitializationsActive + + ControllerInfo->LogicalDeviceInitializationsActive + + ControllerInfo->PhysicalDeviceInitializationsActive + + ControllerInfo->ConsistencyChecksActive + + ControllerInfo->RebuildsActive + + ControllerInfo->OnlineExpansionsActive == 0 || + jiffies - Controller->PrimaryMonitoringTime + < DAC960_MonitoringTimerInterval)) + { + Controller->MonitoringTimer.expires = + jiffies + DAC960_HealthStatusMonitoringInterval; + add_timer(&Controller->MonitoringTimer); + return; + } + Controller->V2.StatusChangeCounter = StatusChangeCounter; + Controller->PrimaryMonitoringTime = jiffies; + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + /* + Queue a Status Monitoring Command to Controller. + */ + Command = DAC960_AllocateCommand(Controller); + if (Command != NULL) + DAC960_V2_QueueMonitoringCommand(Command); + else Controller->MonitoringCommandDeferred = true; + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + /* + Wake up any processes waiting on a Health Status Buffer change. + */ + wake_up(&Controller->HealthStatusWaitQueue); + } } @@ -2642,20 +4828,29 @@ if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1) return -ENXIO; Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL || - LogicalDriveNumber > Controller->LogicalDriveCount - 1) - return -ENXIO; - if (Controller->LogicalDriveInformation - [Controller->LogicalDriveInformationIndex] - [LogicalDriveNumber].LogicalDriveState - == DAC960_LogicalDrive_Offline) - return -ENXIO; - if (Controller->LogicalDriveInitialState[LogicalDriveNumber] - == DAC960_LogicalDrive_Offline) + if (Controller == NULL) return -ENXIO; + if (Controller->FirmwareType == DAC960_V1_Controller) + { + if (LogicalDriveNumber > Controller->LogicalDriveCount - 1) + return -ENXIO; + if (Controller->V1.LogicalDriveInformation + [LogicalDriveNumber].LogicalDriveState + == DAC960_V1_LogicalDrive_Offline) + return -ENXIO; + } + else + { + DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo = + Controller->V2.LogicalDeviceInformation[LogicalDriveNumber]; + if (LogicalDeviceInfo == NULL || + LogicalDeviceInfo->LogicalDeviceState + == DAC960_V2_LogicalDevice_Offline) + return -ENXIO; + } + if (!Controller->LogicalDriveInitiallyAccessible[LogicalDriveNumber]) { - Controller->LogicalDriveInitialState[LogicalDriveNumber] = - DAC960_LogicalDrive_Online; - DAC960_InitializeGenericDiskInfo(&Controller->GenericDiskInfo); + Controller->LogicalDriveInitiallyAccessible[LogicalDriveNumber] = true; + DAC960_RegisterDisk(Controller, LogicalDriveNumber); } if (Controller->GenericDiskInfo.sizes[MINOR(Inode->i_rdev)] == 0) return -ENXIO; @@ -2710,25 +4905,51 @@ if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1) return -ENXIO; Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL || - LogicalDriveNumber > Controller->LogicalDriveCount - 1) - return -ENXIO; + if (Controller == NULL) return -ENXIO; switch (Request) { case HDIO_GETGEO: /* Get BIOS Disk Geometry. */ UserGeometry = (DiskGeometry_T *) Argument; if (UserGeometry == NULL) return -EINVAL; - Geometry.heads = Controller->GeometryTranslationHeads; - Geometry.sectors = Controller->GeometryTranslationSectors; - Geometry.cylinders = - Controller->LogicalDriveInformation - [Controller->LogicalDriveInformationIndex] - [LogicalDriveNumber].LogicalDriveSize - / (Controller->GeometryTranslationHeads * - Controller->GeometryTranslationSectors); - Geometry.start = Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)] - .start_sect; + if (Controller->FirmwareType == DAC960_V1_Controller) + { + if (LogicalDriveNumber > Controller->LogicalDriveCount - 1) + return -ENXIO; + Geometry.heads = Controller->V1.GeometryTranslationHeads; + Geometry.sectors = Controller->V1.GeometryTranslationSectors; + Geometry.cylinders = + Controller->V1.LogicalDriveInformation[LogicalDriveNumber] + .LogicalDriveSize + / (Geometry.heads * Geometry.sectors); + } + else + { + DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo = + Controller->V2.LogicalDeviceInformation[LogicalDriveNumber]; + if (LogicalDeviceInfo == NULL) + return -EINVAL; + switch(LogicalDeviceInfo->DriveGeometry) + { + case DAC960_V2_Geometry_128_32: + Geometry.heads = 128; + Geometry.sectors = 32; + break; + case DAC960_V2_Geometry_255_63: + Geometry.heads = 255; + Geometry.sectors = 63; + break; + default: + DAC960_Error("Illegal Logical Device Geometry %d\n", + Controller, LogicalDeviceInfo->DriveGeometry); + return -EINVAL; + } + Geometry.cylinders = + LogicalDeviceInfo->ConfigurableDeviceSizeIn512ByteBlocksOrMB + / (Geometry.heads * Geometry.sectors); + } + Geometry.start = + Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)].start_sect; return copy_to_user(UserGeometry, &Geometry, sizeof(DiskGeometry_T)); case BLKGETSIZE: /* Get Device Size. */ @@ -2789,13 +5010,20 @@ */ set_blocksize(Device, BLOCK_SIZE); } - /* - * Leonard, I'll tie you, draw around you a pentagram - * and read this file. Aloud. - */ - grok_partitions( - &Controller->GenericDiskInfo, LogicalDriveNumber, DAC960_MaxPartitions, - Controller->LogicalDriveInformation[Controller->LogicalDriveInformationIndex][LogicalDriveNumber].LogicalDriveSize); + if (Controller->FirmwareType == DAC960_V1_Controller) + grok_partitions(&Controller->GenericDiskInfo, + LogicalDriveNumber, + DAC960_MaxPartitions, + Controller->V1.LogicalDriveInformation + [LogicalDriveNumber] + .LogicalDriveSize); + else + grok_partitions( + &Controller->GenericDiskInfo, + LogicalDriveNumber, + DAC960_MaxPartitions, + Controller->V2.LogicalDeviceInformation[LogicalDriveNumber] + ->ConfigurableDeviceSizeIn512ByteBlocksOrMB); return 0; } return -EINVAL; @@ -2830,59 +5058,63 @@ ControllerNumber > DAC960_ControllerCount - 1) return -ENXIO; Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL) - return -ENXIO; + if (Controller == NULL) return -ENXIO; memset(&ControllerInfo, 0, sizeof(DAC960_ControllerInfo_T)); ControllerInfo.ControllerNumber = ControllerNumber; + ControllerInfo.FirmwareType = Controller->FirmwareType; + ControllerInfo.Channels = Controller->Channels; + ControllerInfo.Targets = Controller->Targets; ControllerInfo.PCI_Bus = Controller->Bus; ControllerInfo.PCI_Device = Controller->Device; ControllerInfo.PCI_Function = Controller->Function; ControllerInfo.IRQ_Channel = Controller->IRQ_Channel; - ControllerInfo.Channels = Controller->Channels; ControllerInfo.PCI_Address = Controller->PCI_Address; strcpy(ControllerInfo.ModelName, Controller->ModelName); strcpy(ControllerInfo.FirmwareVersion, Controller->FirmwareVersion); return copy_to_user(UserSpaceControllerInfo, &ControllerInfo, sizeof(DAC960_ControllerInfo_T)); } - case DAC960_IOCTL_EXECUTE_COMMAND: + case DAC960_IOCTL_V1_EXECUTE_COMMAND: { - DAC960_UserCommand_T *UserSpaceUserCommand = - (DAC960_UserCommand_T *) Argument; - DAC960_UserCommand_T UserCommand; + DAC960_V1_UserCommand_T *UserSpaceUserCommand = + (DAC960_V1_UserCommand_T *) Argument; + DAC960_V1_UserCommand_T UserCommand; DAC960_Controller_T *Controller; DAC960_Command_T *Command = NULL; - DAC960_CommandOpcode_T CommandOpcode; - DAC960_CommandStatus_T CommandStatus; - DAC960_DCDB_T DCDB; + DAC960_V1_CommandOpcode_T CommandOpcode; + DAC960_V1_CommandStatus_T CommandStatus; + DAC960_V1_DCDB_T DCDB; ProcessorFlags_T ProcessorFlags; int ControllerNumber, DataTransferLength; unsigned char *DataTransferBuffer = NULL; if (UserSpaceUserCommand == NULL) return -EINVAL; ErrorCode = copy_from_user(&UserCommand, UserSpaceUserCommand, - sizeof(DAC960_UserCommand_T)); - if (ErrorCode != 0) goto Failure; + sizeof(DAC960_V1_UserCommand_T)); + if (ErrorCode != 0) goto Failure1; ControllerNumber = UserCommand.ControllerNumber; if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1) return -ENXIO; Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL) - return -ENXIO; + if (Controller == NULL) return -ENXIO; + if (Controller->FirmwareType != DAC960_V1_Controller) return -EINVAL; CommandOpcode = UserCommand.CommandMailbox.Common.CommandOpcode; DataTransferLength = UserCommand.DataTransferLength; if (CommandOpcode & 0x80) return -EINVAL; - if (CommandOpcode == DAC960_DCDB) + if (CommandOpcode == DAC960_V1_DCDB) { ErrorCode = - copy_from_user(&DCDB, UserCommand.DCDB, sizeof(DAC960_DCDB_T)); - if (ErrorCode != 0) goto Failure; + copy_from_user(&DCDB, UserCommand.DCDB, sizeof(DAC960_V1_DCDB_T)); + if (ErrorCode != 0) goto Failure1; if (!((DataTransferLength == 0 && - DCDB.Direction == DAC960_DCDB_NoDataTransfer) || + DCDB.Direction + == DAC960_V1_DCDB_NoDataTransfer) || (DataTransferLength > 0 && - DCDB.Direction == DAC960_DCDB_DataTransferDeviceToSystem) || + DCDB.Direction + == DAC960_V1_DCDB_DataTransferDeviceToSystem) || (DataTransferLength < 0 && - DCDB.Direction == DAC960_DCDB_DataTransferSystemToDevice))) + DCDB.Direction + == DAC960_V1_DCDB_DataTransferSystemToDevice))) return -EINVAL; if (((DCDB.TransferLengthHigh4 << 16) | DCDB.TransferLength) != abs(DataTransferLength)) @@ -2901,23 +5133,24 @@ ErrorCode = copy_from_user(DataTransferBuffer, UserCommand.DataTransferBuffer, -DataTransferLength); - if (ErrorCode != 0) goto Failure; + if (ErrorCode != 0) goto Failure1; } - if (CommandOpcode == DAC960_DCDB) + if (CommandOpcode == DAC960_V1_DCDB) { DAC960_AcquireControllerLock(Controller, &ProcessorFlags); - while (Controller->DirectCommandActive[DCDB.Channel] - [DCDB.TargetID] || + while (Controller->V1.DirectCommandActive[DCDB.Channel] + [DCDB.TargetID] || (Command = DAC960_AllocateCommand(Controller)) == NULL) DAC960_WaitForCommand(Controller); - Controller->DirectCommandActive[DCDB.Channel] - [DCDB.TargetID] = true; + Controller->V1.DirectCommandActive[DCDB.Channel] + [DCDB.TargetID] = true; DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - DAC960_ClearCommand(Command); + DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; - memcpy(&Command->CommandMailbox, &UserCommand.CommandMailbox, - sizeof(DAC960_CommandMailbox_T)); - Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(&DCDB); + memcpy(&Command->V1.CommandMailbox, &UserCommand.CommandMailbox, + sizeof(DAC960_V1_CommandMailbox_T)); + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(&DCDB); DCDB.BusAddress = Virtual_to_Bus(DataTransferBuffer); } else @@ -2926,38 +5159,211 @@ while ((Command = DAC960_AllocateCommand(Controller)) == NULL) DAC960_WaitForCommand(Controller); DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - DAC960_ClearCommand(Command); + DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; - memcpy(&Command->CommandMailbox, &UserCommand.CommandMailbox, - sizeof(DAC960_CommandMailbox_T)); + memcpy(&Command->V1.CommandMailbox, &UserCommand.CommandMailbox, + sizeof(DAC960_V1_CommandMailbox_T)); if (DataTransferBuffer != NULL) - Command->CommandMailbox.Type3.BusAddress = + Command->V1.CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DataTransferBuffer); } DAC960_ExecuteCommand(Command); - CommandStatus = Command->CommandStatus; + CommandStatus = Command->V1.CommandStatus; DAC960_AcquireControllerLock(Controller, &ProcessorFlags); DAC960_DeallocateCommand(Command); DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - if (CommandStatus == DAC960_NormalCompletion && - DataTransferLength > 0) + if (DataTransferLength > 0) { ErrorCode = copy_to_user(UserCommand.DataTransferBuffer, DataTransferBuffer, DataTransferLength); - if (ErrorCode != 0) goto Failure; + if (ErrorCode != 0) goto Failure1; } - if (CommandOpcode == DAC960_DCDB) + if (CommandOpcode == DAC960_V1_DCDB) { - Controller->DirectCommandActive[DCDB.Channel] - [DCDB.TargetID] = false; + Controller->V1.DirectCommandActive[DCDB.Channel] + [DCDB.TargetID] = false; ErrorCode = - copy_to_user(UserCommand.DCDB, &DCDB, sizeof(DAC960_DCDB_T)); - if (ErrorCode != 0) goto Failure; + copy_to_user(UserCommand.DCDB, &DCDB, sizeof(DAC960_V1_DCDB_T)); + if (ErrorCode != 0) goto Failure1; + } + ErrorCode = CommandStatus; + Failure1: + if (DataTransferBuffer != NULL) + kfree(DataTransferBuffer); + return ErrorCode; + } + case DAC960_IOCTL_V2_EXECUTE_COMMAND: + { + DAC960_V2_UserCommand_T *UserSpaceUserCommand = + (DAC960_V2_UserCommand_T *) Argument; + DAC960_V2_UserCommand_T UserCommand; + DAC960_Controller_T *Controller; + DAC960_Command_T *Command = NULL; + DAC960_V2_CommandMailbox_T *CommandMailbox; + DAC960_V2_CommandStatus_T CommandStatus; + ProcessorFlags_T ProcessorFlags; + int ControllerNumber, DataTransferLength; + int DataTransferResidue, RequestSenseLength; + unsigned char *DataTransferBuffer = NULL; + unsigned char *RequestSenseBuffer = NULL; + if (UserSpaceUserCommand == NULL) return -EINVAL; + ErrorCode = copy_from_user(&UserCommand, UserSpaceUserCommand, + sizeof(DAC960_V2_UserCommand_T)); + if (ErrorCode != 0) goto Failure2; + ControllerNumber = UserCommand.ControllerNumber; + if (ControllerNumber < 0 || + ControllerNumber > DAC960_ControllerCount - 1) + return -ENXIO; + Controller = DAC960_Controllers[ControllerNumber]; + if (Controller == NULL) return -ENXIO; + if (Controller->FirmwareType != DAC960_V2_Controller) return -EINVAL; + DataTransferLength = UserCommand.DataTransferLength; + if (DataTransferLength > 0) + { + DataTransferBuffer = kmalloc(DataTransferLength, GFP_KERNEL); + if (DataTransferBuffer == NULL) return -ENOMEM; + memset(DataTransferBuffer, 0, DataTransferLength); + } + else if (DataTransferLength < 0) + { + DataTransferBuffer = kmalloc(-DataTransferLength, GFP_KERNEL); + if (DataTransferBuffer == NULL) return -ENOMEM; + ErrorCode = copy_from_user(DataTransferBuffer, + UserCommand.DataTransferBuffer, + -DataTransferLength); + if (ErrorCode != 0) goto Failure2; + } + RequestSenseLength = UserCommand.RequestSenseLength; + if (RequestSenseLength > 0) + { + RequestSenseBuffer = kmalloc(RequestSenseLength, GFP_KERNEL); + if (RequestSenseBuffer == NULL) + { + ErrorCode = -ENOMEM; + goto Failure2; + } + memset(RequestSenseBuffer, 0, RequestSenseLength); + } + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + while ((Command = DAC960_AllocateCommand(Controller)) == NULL) + DAC960_WaitForCommand(Controller); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + DAC960_V2_ClearCommand(Command); + Command->CommandType = DAC960_ImmediateCommand; + CommandMailbox = &Command->V2.CommandMailbox; + memcpy(CommandMailbox, &UserCommand.CommandMailbox, + sizeof(DAC960_V2_CommandMailbox_T)); + CommandMailbox->Common.CommandControlBits + .AdditionalScatterGatherListMemory = false; + CommandMailbox->Common.CommandControlBits + .NoAutoRequestSense = true; + CommandMailbox->Common.DataTransferSize = 0; + CommandMailbox->Common.DataTransferPageNumber = 0; + memset(&CommandMailbox->Common.DataTransferMemoryAddress, 0, + sizeof(DAC960_V2_DataTransferMemoryAddress_T)); + if (DataTransferLength != 0) + { + if (DataTransferLength > 0) + { + CommandMailbox->Common.CommandControlBits + .DataTransferControllerToHost = true; + CommandMailbox->Common.DataTransferSize = DataTransferLength; + } + else + { + CommandMailbox->Common.CommandControlBits + .DataTransferControllerToHost = false; + CommandMailbox->Common.DataTransferSize = -DataTransferLength; + } + CommandMailbox->Common.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(DataTransferBuffer); + CommandMailbox->Common.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->Common.DataTransferSize; + } + if (RequestSenseLength > 0) + { + CommandMailbox->Common.CommandControlBits + .NoAutoRequestSense = false; + CommandMailbox->Common.RequestSenseSize = RequestSenseLength; + CommandMailbox->Common.RequestSenseBusAddress = + Virtual_to_Bus(RequestSenseBuffer); + } + DAC960_ExecuteCommand(Command); + CommandStatus = Command->V2.CommandStatus; + RequestSenseLength = Command->V2.RequestSenseLength; + DataTransferResidue = Command->V2.DataTransferResidue; + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + DAC960_DeallocateCommand(Command); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + if (RequestSenseLength > UserCommand.RequestSenseLength) + RequestSenseLength = UserCommand.RequestSenseLength; + ErrorCode = copy_to_user(&UserSpaceUserCommand->DataTransferLength, + &DataTransferResidue, + sizeof(DataTransferResidue)); + if (ErrorCode != 0) goto Failure2; + ErrorCode = copy_to_user(&UserSpaceUserCommand->RequestSenseLength, + &RequestSenseLength, + sizeof(RequestSenseLength)); + if (ErrorCode != 0) goto Failure2; + if (DataTransferLength > 0) + { + ErrorCode = copy_to_user(UserCommand.DataTransferBuffer, + DataTransferBuffer, DataTransferLength); + if (ErrorCode != 0) goto Failure2; + } + if (RequestSenseLength > 0) + { + ErrorCode = copy_to_user(UserCommand.RequestSenseBuffer, + RequestSenseBuffer, RequestSenseLength); + if (ErrorCode != 0) goto Failure2; } ErrorCode = CommandStatus; - Failure: + Failure2: if (DataTransferBuffer != NULL) kfree(DataTransferBuffer); + if (RequestSenseBuffer != NULL) + kfree(RequestSenseBuffer); + return ErrorCode; + } + case DAC960_IOCTL_V2_GET_HEALTH_STATUS: + { + DAC960_V2_GetHealthStatus_T *UserSpaceGetHealthStatus = + (DAC960_V2_GetHealthStatus_T *) Argument; + DAC960_V2_GetHealthStatus_T GetHealthStatus; + DAC960_V2_HealthStatusBuffer_T HealthStatusBuffer; + DAC960_Controller_T *Controller; + int ControllerNumber; + if (UserSpaceGetHealthStatus == NULL) return -EINVAL; + ErrorCode = copy_from_user(&GetHealthStatus, UserSpaceGetHealthStatus, + sizeof(DAC960_V2_GetHealthStatus_T)); + if (ErrorCode != 0) return ErrorCode; + ControllerNumber = GetHealthStatus.ControllerNumber; + if (ControllerNumber < 0 || + ControllerNumber > DAC960_ControllerCount - 1) + return -ENXIO; + Controller = DAC960_Controllers[ControllerNumber]; + if (Controller == NULL) return -ENXIO; + if (Controller->FirmwareType != DAC960_V2_Controller) return -EINVAL; + ErrorCode = copy_from_user(&HealthStatusBuffer, + GetHealthStatus.HealthStatusBuffer, + sizeof(DAC960_V2_HealthStatusBuffer_T)); + if (ErrorCode != 0) return ErrorCode; + while (Controller->V2.HealthStatusBuffer->StatusChangeCounter + == HealthStatusBuffer.StatusChangeCounter && + Controller->V2.HealthStatusBuffer->NextEventSequenceNumber + == HealthStatusBuffer.NextEventSequenceNumber) + { + interruptible_sleep_on_timeout(&Controller->HealthStatusWaitQueue, + DAC960_MonitoringTimerInterval); + if (signal_pending(current)) return -EINTR; + } + ErrorCode = copy_to_user(GetHealthStatus.HealthStatusBuffer, + Controller->V2.HealthStatusBuffer, + sizeof(DAC960_V2_HealthStatusBuffer_T)); return ErrorCode; } } @@ -2987,28 +5393,29 @@ ControllerNumber > DAC960_ControllerCount - 1) return -ENXIO; Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL) - return -ENXIO; + if (Controller == NULL) return -ENXIO; memset(ControllerInfo, 0, sizeof(DAC960_ControllerInfo_T)); ControllerInfo->ControllerNumber = ControllerNumber; + ControllerInfo->FirmwareType = Controller->FirmwareType; + ControllerInfo->Channels = Controller->Channels; + ControllerInfo->Targets = Controller->Targets; ControllerInfo->PCI_Bus = Controller->Bus; ControllerInfo->PCI_Device = Controller->Device; ControllerInfo->PCI_Function = Controller->Function; ControllerInfo->IRQ_Channel = Controller->IRQ_Channel; - ControllerInfo->Channels = Controller->Channels; ControllerInfo->PCI_Address = Controller->PCI_Address; strcpy(ControllerInfo->ModelName, Controller->ModelName); strcpy(ControllerInfo->FirmwareVersion, Controller->FirmwareVersion); return 0; } - case DAC960_IOCTL_EXECUTE_COMMAND: + case DAC960_IOCTL_V1_EXECUTE_COMMAND: { - DAC960_KernelCommand_T *KernelCommand = - (DAC960_KernelCommand_T *) Argument; + DAC960_V1_KernelCommand_T *KernelCommand = + (DAC960_V1_KernelCommand_T *) Argument; DAC960_Controller_T *Controller; DAC960_Command_T *Command = NULL; - DAC960_CommandOpcode_T CommandOpcode; - DAC960_DCDB_T *DCDB = NULL; + DAC960_V1_CommandOpcode_T CommandOpcode; + DAC960_V1_DCDB_T *DCDB = NULL; ProcessorFlags_T ProcessorFlags; int ControllerNumber, DataTransferLength; unsigned char *DataTransferBuffer = NULL; @@ -3018,21 +5425,23 @@ ControllerNumber > DAC960_ControllerCount - 1) return -ENXIO; Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL) - return -ENXIO; + if (Controller == NULL) return -ENXIO; + if (Controller->FirmwareType != DAC960_V1_Controller) return -EINVAL; CommandOpcode = KernelCommand->CommandMailbox.Common.CommandOpcode; DataTransferLength = KernelCommand->DataTransferLength; DataTransferBuffer = KernelCommand->DataTransferBuffer; if (CommandOpcode & 0x80) return -EINVAL; - if (CommandOpcode == DAC960_DCDB) + if (CommandOpcode == DAC960_V1_DCDB) { DCDB = KernelCommand->DCDB; if (!((DataTransferLength == 0 && - DCDB->Direction == DAC960_DCDB_NoDataTransfer) || + DCDB->Direction == DAC960_V1_DCDB_NoDataTransfer) || (DataTransferLength > 0 && - DCDB->Direction == DAC960_DCDB_DataTransferDeviceToSystem) || + DCDB->Direction + == DAC960_V1_DCDB_DataTransferDeviceToSystem) || (DataTransferLength < 0 && - DCDB->Direction == DAC960_DCDB_DataTransferSystemToDevice))) + DCDB->Direction + == DAC960_V1_DCDB_DataTransferSystemToDevice))) return -EINVAL; if (((DCDB->TransferLengthHigh4 << 16) | DCDB->TransferLength) != abs(DataTransferLength)) @@ -3042,25 +5451,26 @@ return -EINVAL; if (DataTransferLength > 0) memset(DataTransferBuffer, 0, DataTransferLength); - if (CommandOpcode == DAC960_DCDB) + if (CommandOpcode == DAC960_V1_DCDB) { DAC960_AcquireControllerLock(Controller, &ProcessorFlags); - if (!Controller->DirectCommandActive[DCDB->Channel] - [DCDB->TargetID]) + if (!Controller->V1.DirectCommandActive[DCDB->Channel] + [DCDB->TargetID]) Command = DAC960_AllocateCommand(Controller); if (Command == NULL) { DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); return -EBUSY; } - else Controller->DirectCommandActive[DCDB->Channel] - [DCDB->TargetID] = true; - DAC960_ClearCommand(Command); + else Controller->V1.DirectCommandActive[DCDB->Channel] + [DCDB->TargetID] = true; + DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_QueuedCommand; - memcpy(&Command->CommandMailbox, &KernelCommand->CommandMailbox, - sizeof(DAC960_CommandMailbox_T)); - Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB); - Command->KernelCommand = KernelCommand; + memcpy(&Command->V1.CommandMailbox, &KernelCommand->CommandMailbox, + sizeof(DAC960_V1_CommandMailbox_T)); + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(DCDB); + Command->V1.KernelCommand = KernelCommand; DCDB->BusAddress = Virtual_to_Bus(DataTransferBuffer); DAC960_QueueCommand(Command); DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); @@ -3074,44 +5484,153 @@ DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); return -EBUSY; } - DAC960_ClearCommand(Command); + DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_QueuedCommand; - memcpy(&Command->CommandMailbox, &KernelCommand->CommandMailbox, - sizeof(DAC960_CommandMailbox_T)); + memcpy(&Command->V1.CommandMailbox, &KernelCommand->CommandMailbox, + sizeof(DAC960_V1_CommandMailbox_T)); if (DataTransferBuffer != NULL) - Command->CommandMailbox.Type3.BusAddress = + Command->V1.CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DataTransferBuffer); - Command->KernelCommand = KernelCommand; + Command->V1.KernelCommand = KernelCommand; DAC960_QueueCommand(Command); DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); } return 0; } + case DAC960_IOCTL_V2_EXECUTE_COMMAND: + { + DAC960_V2_KernelCommand_T *KernelCommand = + (DAC960_V2_KernelCommand_T *) Argument; + DAC960_Controller_T *Controller; + DAC960_Command_T *Command = NULL; + DAC960_V2_CommandMailbox_T *CommandMailbox; + ProcessorFlags_T ProcessorFlags; + int ControllerNumber, DataTransferLength, RequestSenseLength; + unsigned char *DataTransferBuffer = NULL; + unsigned char *RequestSenseBuffer = NULL; + if (KernelCommand == NULL) return -EINVAL; + ControllerNumber = KernelCommand->ControllerNumber; + if (ControllerNumber < 0 || + ControllerNumber > DAC960_ControllerCount - 1) + return -ENXIO; + Controller = DAC960_Controllers[ControllerNumber]; + if (Controller == NULL) return -ENXIO; + if (Controller->FirmwareType != DAC960_V2_Controller) return -EINVAL; + DataTransferLength = KernelCommand->DataTransferLength; + RequestSenseLength = KernelCommand->RequestSenseLength; + DataTransferBuffer = KernelCommand->DataTransferBuffer; + RequestSenseBuffer = KernelCommand->RequestSenseBuffer; + if (DataTransferLength != 0 && DataTransferBuffer == NULL) + return -EINVAL; + if (RequestSenseLength < 0) + return -EINVAL; + if (RequestSenseLength > 0 && RequestSenseBuffer == NULL) + return -EINVAL; + if (DataTransferLength > 0) + memset(DataTransferBuffer, 0, DataTransferLength); + if (RequestSenseLength > 0) + memset(RequestSenseBuffer, 0, RequestSenseLength); + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + Command = DAC960_AllocateCommand(Controller); + if (Command == NULL) + { + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + return -EBUSY; + } + DAC960_V2_ClearCommand(Command); + Command->CommandType = DAC960_QueuedCommand; + CommandMailbox = &Command->V2.CommandMailbox; + memcpy(CommandMailbox, &KernelCommand->CommandMailbox, + sizeof(DAC960_V2_CommandMailbox_T)); + CommandMailbox->Common.CommandControlBits + .AdditionalScatterGatherListMemory = false; + CommandMailbox->Common.CommandControlBits + .NoAutoRequestSense = true; + CommandMailbox->Common.DataTransferSize = 0; + CommandMailbox->Common.DataTransferPageNumber = 0; + memset(&CommandMailbox->Common.DataTransferMemoryAddress, 0, + sizeof(DAC960_V2_DataTransferMemoryAddress_T)); + if (DataTransferLength != 0) + { + if (DataTransferLength > 0) + { + CommandMailbox->Common.CommandControlBits + .DataTransferControllerToHost = true; + CommandMailbox->Common.DataTransferSize = DataTransferLength; + } + else + { + CommandMailbox->Common.CommandControlBits + .DataTransferControllerToHost = false; + CommandMailbox->Common.DataTransferSize = -DataTransferLength; + } + CommandMailbox->Common.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(DataTransferBuffer); + CommandMailbox->Common.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->Common.DataTransferSize; + } + if (RequestSenseLength > 0) + { + CommandMailbox->Common.CommandControlBits + .NoAutoRequestSense = false; + CommandMailbox->Common.RequestSenseBusAddress = + Virtual_to_Bus(RequestSenseBuffer); + } + Command->V2.KernelCommand = KernelCommand; + DAC960_QueueCommand(Command); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + return 0; + } } return -EINVAL; } /* - DAC960_GenericDiskInit is the Generic Disk Information Initialization - Function for the DAC960 Driver. -*/ - -static void DAC960_InitializeGenericDiskInfo(GenericDiskInfo_T *GenericDiskInfo) -{ - DAC960_Controller_T *Controller = - (DAC960_Controller_T *) GenericDiskInfo->real_devices; - DAC960_LogicalDriveInformation_T *LogicalDriveInformation = - Controller->LogicalDriveInformation - [Controller->LogicalDriveInformationIndex]; - int LogicalDriveNumber; - for (LogicalDriveNumber = 0; - LogicalDriveNumber < Controller->LogicalDriveCount; - LogicalDriveNumber++) - register_disk(GenericDiskInfo, MKDEV(GenericDiskInfo->major, - LogicalDriveNumber*DAC960_MaxPartitions), - DAC960_MaxPartitions, &DAC960_FileOperations, - LogicalDriveInformation[LogicalDriveNumber].LogicalDriveSize); + DAC960_CheckStatusBuffer verifies that there is room to hold ByteCount + additional bytes in the Combined Status Buffer and grows the buffer if + necessary. It returns true if there is enough room and false otherwise. +*/ + +static boolean DAC960_CheckStatusBuffer(DAC960_Controller_T *Controller, + unsigned int ByteCount) +{ + unsigned char *NewStatusBuffer; + if (Controller->InitialStatusLength + 1 + + Controller->CurrentStatusLength + ByteCount + 1 <= + Controller->CombinedStatusBufferLength) + return true; + if (Controller->CombinedStatusBufferLength == 0) + { + unsigned int NewStatusBufferLength = DAC960_InitialStatusBufferSize; + while (NewStatusBufferLength < ByteCount) + NewStatusBufferLength *= 2; + Controller->CombinedStatusBuffer = + (unsigned char *) kmalloc(NewStatusBufferLength, GFP_ATOMIC); + if (Controller->CombinedStatusBuffer == NULL) return false; + Controller->CombinedStatusBufferLength = NewStatusBufferLength; + return true; + } + NewStatusBuffer = (unsigned char *) + kmalloc(2 * Controller->CombinedStatusBufferLength, GFP_ATOMIC); + if (NewStatusBuffer == NULL) + { + DAC960_Warning("Unable to expand Combined Status Buffer - Truncating\n", + Controller); + return false; + } + memcpy(NewStatusBuffer, Controller->CombinedStatusBuffer, + Controller->CombinedStatusBufferLength); + kfree(Controller->CombinedStatusBuffer); + Controller->CombinedStatusBuffer = NewStatusBuffer; + Controller->CombinedStatusBufferLength *= 2; + Controller->CurrentStatusBuffer = + &NewStatusBuffer[Controller->InitialStatusLength + 1]; + return true; } @@ -3120,11 +5639,11 @@ */ static void DAC960_Message(DAC960_MessageLevel_T MessageLevel, - char *Format, + unsigned char *Format, DAC960_Controller_T *Controller, ...) { - static char Buffer[DAC960_LineBufferSize]; + static unsigned char Buffer[DAC960_LineBufferSize]; static boolean BeginningOfLine = true; va_list Arguments; int Length = 0; @@ -3139,9 +5658,16 @@ { if (!Controller->ControllerInitialized) { - strcpy(&Controller->InitialStatusBuffer[ - Controller->InitialStatusLength], Buffer); - Controller->InitialStatusLength += Length; + if (DAC960_CheckStatusBuffer(Controller, Length)) + { + strcpy(&Controller->CombinedStatusBuffer + [Controller->InitialStatusLength], + Buffer); + Controller->InitialStatusLength += Length; + Controller->CurrentStatusBuffer = + &Controller->CombinedStatusBuffer + [Controller->InitialStatusLength + 1]; + } if (MessageLevel == DAC960_AnnounceLevel) { static int AnnouncementLines = 0; @@ -3161,7 +5687,7 @@ else printk("%s", Buffer); } } - else + else if (DAC960_CheckStatusBuffer(Controller, Length)) { strcpy(&Controller->CurrentStatusBuffer[ Controller->CurrentStatusLength], Buffer); @@ -3170,8 +5696,8 @@ } else if (MessageLevel == DAC960_ProgressLevel) { - strcpy(Controller->RebuildProgressBuffer, Buffer); - Controller->RebuildProgressLength = Length; + strcpy(Controller->ProgressBuffer, Buffer); + Controller->ProgressBufferLength = Length; if (Controller->EphemeralProgressMessage) { if (jiffies - Controller->LastProgressReportTime @@ -3206,15 +5732,15 @@ /* - DAC960_ParsePhysicalDrive parses spaces followed by a Physical Drive + DAC960_ParsePhysicalDevice parses spaces followed by a Physical Device Channel:TargetID specification from a User Command string. It updates - Channel and TargetID and returns true on success and returns false otherwise. + Channel and TargetID and returns true on success and false on failure. */ -static boolean DAC960_ParsePhysicalDrive(DAC960_Controller_T *Controller, - char *UserCommandString, - unsigned char *Channel, - unsigned char *TargetID) +static boolean DAC960_ParsePhysicalDevice(DAC960_Controller_T *Controller, + char *UserCommandString, + unsigned char *Channel, + unsigned char *TargetID) { char *NewUserCommandString = UserCommandString; unsigned long XChannel, XTargetID; @@ -3230,7 +5756,7 @@ XTargetID = simple_strtoul(UserCommandString, &NewUserCommandString, 10); if (NewUserCommandString == UserCommandString || *NewUserCommandString != '\0' || - XTargetID >= DAC960_MaxTargets) + XTargetID >= Controller->Targets) return false; *Channel = XChannel; *TargetID = XTargetID; @@ -3241,7 +5767,7 @@ /* DAC960_ParseLogicalDrive parses spaces followed by a Logical Drive Number specification from a User Command string. It updates LogicalDriveNumber and - returns true on success and returns false otherwise. + returns true on success and false on failure. */ static boolean DAC960_ParseLogicalDrive(DAC960_Controller_T *Controller, @@ -3257,7 +5783,7 @@ simple_strtoul(UserCommandString, &NewUserCommandString, 10); if (NewUserCommandString == UserCommandString || *NewUserCommandString != '\0' || - XLogicalDriveNumber >= Controller->LogicalDriveCount) + XLogicalDriveNumber > DAC960_MaxLogicalDrives - 1) return false; *LogicalDriveNumber = XLogicalDriveNumber; return true; @@ -3265,68 +5791,71 @@ /* - DAC960_SetDeviceState sets the Device State for a Physical Drive. + DAC960_V1_SetDeviceState sets the Device State for a Physical Device for + DAC960 V1 Firmware Controllers. */ -static void DAC960_SetDeviceState(DAC960_Controller_T *Controller, - DAC960_Command_T *Command, - unsigned char Channel, - unsigned char TargetID, - DAC960_PhysicalDeviceState_T DeviceState, - const char *DeviceStateString) +static void DAC960_V1_SetDeviceState(DAC960_Controller_T *Controller, + DAC960_Command_T *Command, + unsigned char Channel, + unsigned char TargetID, + DAC960_V1_PhysicalDeviceState_T + DeviceState, + const unsigned char *DeviceStateString) { - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; - CommandMailbox->Type3D.CommandOpcode = DAC960_StartDevice; + DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + CommandMailbox->Type3D.CommandOpcode = DAC960_V1_StartDevice; CommandMailbox->Type3D.Channel = Channel; CommandMailbox->Type3D.TargetID = TargetID; CommandMailbox->Type3D.DeviceState = DeviceState; CommandMailbox->Type3D.Modifier = 0; DAC960_ExecuteCommand(Command); - switch (Command->CommandStatus) + switch (Command->V1.CommandStatus) { - case DAC960_NormalCompletion: - DAC960_UserCritical("%s of Physical Drive %d:%d Succeeded\n", Controller, + case DAC960_V1_NormalCompletion: + DAC960_UserCritical("%s of Physical Device %d:%d Succeeded\n", Controller, DeviceStateString, Channel, TargetID); break; - case DAC960_UnableToStartDevice: - DAC960_UserCritical("%s of Physical Drive %d:%d Failed - " + case DAC960_V1_UnableToStartDevice: + DAC960_UserCritical("%s of Physical Device %d:%d Failed - " "Unable to Start Device\n", Controller, DeviceStateString, Channel, TargetID); break; - case DAC960_NoDeviceAtAddress: - DAC960_UserCritical("%s of Physical Drive %d:%d Failed - " + case DAC960_V1_NoDeviceAtAddress: + DAC960_UserCritical("%s of Physical Device %d:%d Failed - " "No Device at Address\n", Controller, DeviceStateString, Channel, TargetID); break; - case DAC960_InvalidChannelOrTargetOrModifier: - DAC960_UserCritical("%s of Physical Drive %d:%d Failed - " + case DAC960_V1_InvalidChannelOrTargetOrModifier: + DAC960_UserCritical("%s of Physical Device %d:%d Failed - " "Invalid Channel or Target or Modifier\n", Controller, DeviceStateString, Channel, TargetID); break; - case DAC960_ChannelBusy: - DAC960_UserCritical("%s of Physical Drive %d:%d Failed - " + case DAC960_V1_ChannelBusy: + DAC960_UserCritical("%s of Physical Device %d:%d Failed - " "Channel Busy\n", Controller, DeviceStateString, Channel, TargetID); break; default: - DAC960_UserCritical("%s of Physical Drive %d:%d Failed - " + DAC960_UserCritical("%s of Physical Device %d:%d Failed - " "Unexpected Status %04X\n", Controller, DeviceStateString, Channel, TargetID, - Command->CommandStatus); + Command->V1.CommandStatus); break; } } /* - DAC960_ExecuteUserCommand executes a User Command. + DAC960_V1_ExecuteUserCommand executes a User Command for DAC960 V1 Firmware + Controllers. */ -static boolean DAC960_ExecuteUserCommand(DAC960_Controller_T *Controller, - char *UserCommand) +static boolean DAC960_V1_ExecuteUserCommand(DAC960_Controller_T *Controller, + unsigned char *UserCommand) { DAC960_Command_T *Command; - DAC960_CommandMailbox_T *CommandMailbox; + DAC960_V1_CommandMailbox_T *CommandMailbox; ProcessorFlags_T ProcessorFlags; unsigned char Channel, TargetID, LogicalDriveNumber; DAC960_AcquireControllerLock(Controller, &ProcessorFlags); @@ -3334,100 +5863,98 @@ DAC960_WaitForCommand(Controller); DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); Controller->UserStatusLength = 0; - DAC960_ClearCommand(Command); + DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; - CommandMailbox = &Command->CommandMailbox; + CommandMailbox = &Command->V1.CommandMailbox; if (strcmp(UserCommand, "flush-cache") == 0) { - CommandMailbox->Type3.CommandOpcode = DAC960_Flush; + CommandMailbox->Type3.CommandOpcode = DAC960_V1_Flush; DAC960_ExecuteCommand(Command); DAC960_UserCritical("Cache Flush Completed\n", Controller); } else if (strncmp(UserCommand, "kill", 4) == 0 && - DAC960_ParsePhysicalDrive(Controller, &UserCommand[4], - &Channel, &TargetID)) + DAC960_ParsePhysicalDevice(Controller, &UserCommand[4], + &Channel, &TargetID)) { - DAC960_DeviceState_T *DeviceState = - &Controller->DeviceState[Controller->DeviceStateIndex] - [Channel][TargetID]; + DAC960_V1_DeviceState_T *DeviceState = + &Controller->V1.DeviceState[Channel][TargetID]; if (DeviceState->Present && - DeviceState->DeviceType == DAC960_DiskType && - DeviceState->DeviceState != DAC960_Device_Dead) - DAC960_SetDeviceState(Controller, Command, Channel, TargetID, - DAC960_Device_Dead, "Kill"); - else DAC960_UserCritical("Kill of Physical Drive %d:%d Illegal\n", + DeviceState->DeviceType == DAC960_V1_DiskType && + DeviceState->DeviceState != DAC960_V1_Device_Dead) + DAC960_V1_SetDeviceState(Controller, Command, Channel, TargetID, + DAC960_V1_Device_Dead, "Kill"); + else DAC960_UserCritical("Kill of Physical Device %d:%d Illegal\n", Controller, Channel, TargetID); } else if (strncmp(UserCommand, "make-online", 11) == 0 && - DAC960_ParsePhysicalDrive(Controller, &UserCommand[11], - &Channel, &TargetID)) + DAC960_ParsePhysicalDevice(Controller, &UserCommand[11], + &Channel, &TargetID)) { - DAC960_DeviceState_T *DeviceState = - &Controller->DeviceState[Controller->DeviceStateIndex] - [Channel][TargetID]; + DAC960_V1_DeviceState_T *DeviceState = + &Controller->V1.DeviceState[Channel][TargetID]; if (DeviceState->Present && - DeviceState->DeviceType == DAC960_DiskType && - DeviceState->DeviceState == DAC960_Device_Dead) - DAC960_SetDeviceState(Controller, Command, Channel, TargetID, - DAC960_Device_Online, "Make Online"); - else DAC960_UserCritical("Make Online of Physical Drive %d:%d Illegal\n", + DeviceState->DeviceType == DAC960_V1_DiskType && + DeviceState->DeviceState == DAC960_V1_Device_Dead) + DAC960_V1_SetDeviceState(Controller, Command, Channel, TargetID, + DAC960_V1_Device_Online, "Make Online"); + else DAC960_UserCritical("Make Online of Physical Device %d:%d Illegal\n", Controller, Channel, TargetID); } else if (strncmp(UserCommand, "make-standby", 12) == 0 && - DAC960_ParsePhysicalDrive(Controller, &UserCommand[12], - &Channel, &TargetID)) + DAC960_ParsePhysicalDevice(Controller, &UserCommand[12], + &Channel, &TargetID)) { - DAC960_DeviceState_T *DeviceState = - &Controller->DeviceState[Controller->DeviceStateIndex] - [Channel][TargetID]; + DAC960_V1_DeviceState_T *DeviceState = + &Controller->V1.DeviceState[Channel][TargetID]; if (DeviceState->Present && - DeviceState->DeviceType == DAC960_DiskType && - DeviceState->DeviceState == DAC960_Device_Dead) - DAC960_SetDeviceState(Controller, Command, Channel, TargetID, - DAC960_Device_Standby, "Make Standby"); - else DAC960_UserCritical("Make Standby of Physical Drive %d:%d Illegal\n", + DeviceState->DeviceType == DAC960_V1_DiskType && + DeviceState->DeviceState == DAC960_V1_Device_Dead) + DAC960_V1_SetDeviceState(Controller, Command, Channel, TargetID, + DAC960_V1_Device_Standby, "Make Standby"); + else DAC960_UserCritical("Make Standby of Physical " + "Device %d:%d Illegal\n", Controller, Channel, TargetID); } else if (strncmp(UserCommand, "rebuild", 7) == 0 && - DAC960_ParsePhysicalDrive(Controller, &UserCommand[7], - &Channel, &TargetID)) + DAC960_ParsePhysicalDevice(Controller, &UserCommand[7], + &Channel, &TargetID)) { - CommandMailbox->Type3D.CommandOpcode = DAC960_RebuildAsync; + CommandMailbox->Type3D.CommandOpcode = DAC960_V1_RebuildAsync; CommandMailbox->Type3D.Channel = Channel; CommandMailbox->Type3D.TargetID = TargetID; DAC960_ExecuteCommand(Command); - switch (Command->CommandStatus) + switch (Command->V1.CommandStatus) { - case DAC960_NormalCompletion: - DAC960_UserCritical("Rebuild of Physical Drive %d:%d Initiated\n", + case DAC960_V1_NormalCompletion: + DAC960_UserCritical("Rebuild of Physical Device %d:%d Initiated\n", Controller, Channel, TargetID); break; - case DAC960_AttemptToRebuildOnlineDrive: - DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - " + case DAC960_V1_AttemptToRebuildOnlineDrive: + DAC960_UserCritical("Rebuild of Physical Device %d:%d Failed - " "Attempt to Rebuild Online or " "Unresponsive Drive\n", Controller, Channel, TargetID); break; - case DAC960_NewDiskFailedDuringRebuild: - DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - " + case DAC960_V1_NewDiskFailedDuringRebuild: + DAC960_UserCritical("Rebuild of Physical Device %d:%d Failed - " "New Disk Failed During Rebuild\n", Controller, Channel, TargetID); break; - case DAC960_InvalidDeviceAddress: - DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - " + case DAC960_V1_InvalidDeviceAddress: + DAC960_UserCritical("Rebuild of Physical Device %d:%d Failed - " "Invalid Device Address\n", Controller, Channel, TargetID); break; - case DAC960_RebuildOrCheckAlreadyInProgress: - DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - " + case DAC960_V1_RebuildOrCheckAlreadyInProgress: + DAC960_UserCritical("Rebuild of Physical Device %d:%d Failed - " "Rebuild or Consistency Check Already " "in Progress\n", Controller, Channel, TargetID); break; default: - DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - " + DAC960_UserCritical("Rebuild of Physical Device %d:%d Failed - " "Unexpected Status %04X\n", Controller, - Channel, TargetID, Command->CommandStatus); + Channel, TargetID, Command->V1.CommandStatus); break; } } @@ -3435,28 +5962,28 @@ DAC960_ParseLogicalDrive(Controller, &UserCommand[17], &LogicalDriveNumber)) { - CommandMailbox->Type3C.CommandOpcode = DAC960_CheckConsistencyAsync; + CommandMailbox->Type3C.CommandOpcode = DAC960_V1_CheckConsistencyAsync; CommandMailbox->Type3C.LogicalDriveNumber = LogicalDriveNumber; CommandMailbox->Type3C.AutoRestore = true; DAC960_ExecuteCommand(Command); - switch (Command->CommandStatus) + switch (Command->V1.CommandStatus) { - case DAC960_NormalCompletion: + case DAC960_V1_NormalCompletion: DAC960_UserCritical("Consistency Check of Logical Drive %d " "(/dev/rd/c%dd%d) Initiated\n", Controller, LogicalDriveNumber, Controller->ControllerNumber, LogicalDriveNumber); break; - case DAC960_DependentDiskIsDead: + case DAC960_V1_DependentDiskIsDead: DAC960_UserCritical("Consistency Check of Logical Drive %d " "(/dev/rd/c%dd%d) Failed - " - "Dependent Physical Drive is DEAD\n", + "Dependent Physical Device is DEAD\n", Controller, LogicalDriveNumber, Controller->ControllerNumber, LogicalDriveNumber); break; - case DAC960_InvalidOrNonredundantLogicalDrive: + case DAC960_V1_InvalidOrNonredundantLogicalDrive: DAC960_UserCritical("Consistency Check of Logical Drive %d " "(/dev/rd/c%dd%d) Failed - " "Invalid or Nonredundant Logical Drive\n", @@ -3464,7 +5991,7 @@ Controller->ControllerNumber, LogicalDriveNumber); break; - case DAC960_RebuildOrCheckAlreadyInProgress: + case DAC960_V1_RebuildOrCheckAlreadyInProgress: DAC960_UserCritical("Consistency Check of Logical Drive %d " "(/dev/rd/c%dd%d) Failed - Rebuild or " "Consistency Check Already in Progress\n", @@ -3478,7 +6005,7 @@ "Unexpected Status %04X\n", Controller, LogicalDriveNumber, Controller->ControllerNumber, - LogicalDriveNumber, Command->CommandStatus); + LogicalDriveNumber, Command->V1.CommandStatus); break; } } @@ -3486,14 +6013,14 @@ strcmp(UserCommand, "cancel-consistency-check") == 0) { unsigned char OldRebuildRateConstant; - CommandMailbox->Type3R.CommandOpcode = DAC960_RebuildControl; + CommandMailbox->Type3R.CommandOpcode = DAC960_V1_RebuildControl; CommandMailbox->Type3R.RebuildRateConstant = 0xFF; CommandMailbox->Type3R.BusAddress = Virtual_to_Bus(&OldRebuildRateConstant); DAC960_ExecuteCommand(Command); - switch (Command->CommandStatus) + switch (Command->V1.CommandStatus) { - case DAC960_NormalCompletion: + case DAC960_V1_NormalCompletion: DAC960_UserCritical("Rebuild or Consistency Check Cancelled\n", Controller); break; @@ -3501,7 +6028,7 @@ DAC960_UserCritical("Cancellation of Rebuild or " "Consistency Check Failed - " "Unexpected Status %04X\n", - Controller, Command->CommandStatus); + Controller, Command->V1.CommandStatus); break; } } @@ -3515,25 +6042,235 @@ /* + DAC960_V2_TranslatePhysicalDevice translates a Physical Device Channel and + TargetID into a Logical Device. It returns true on success and false + on failure. +*/ + +static boolean DAC960_V2_TranslatePhysicalDevice(DAC960_Command_T *Command, + unsigned char Channel, + unsigned char TargetID, + unsigned short + *LogicalDeviceNumber) +{ + DAC960_V2_CommandMailbox_T SavedCommandMailbox, *CommandMailbox; + DAC960_V2_PhysicalToLogicalDevice_T PhysicalToLogicalDevice; + CommandMailbox = &Command->V2.CommandMailbox; + memcpy(&SavedCommandMailbox, CommandMailbox, + sizeof(DAC960_V2_CommandMailbox_T)); + CommandMailbox->PhysicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->PhysicalDeviceInfo.CommandControlBits + .DataTransferControllerToHost = true; + CommandMailbox->PhysicalDeviceInfo.CommandControlBits + .NoAutoRequestSense = true; + CommandMailbox->PhysicalDeviceInfo.DataTransferSize = + sizeof(DAC960_V2_PhysicalToLogicalDevice_T); + CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.TargetID = TargetID; + CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.Channel = Channel; + CommandMailbox->PhysicalDeviceInfo.IOCTL_Opcode = + DAC960_V2_TranslatePhysicalToLogicalDevice; + CommandMailbox->Common.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(&PhysicalToLogicalDevice); + CommandMailbox->Common.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->Common.DataTransferSize; + DAC960_ExecuteCommand(Command); + memcpy(CommandMailbox, &SavedCommandMailbox, + sizeof(DAC960_V2_CommandMailbox_T)); + *LogicalDeviceNumber = PhysicalToLogicalDevice.LogicalDeviceNumber; + return (Command->V2.CommandStatus == DAC960_V2_NormalCompletion); +} + + +/* + DAC960_V2_ExecuteUserCommand executes a User Command for DAC960 V2 Firmware + Controllers. +*/ + +static boolean DAC960_V2_ExecuteUserCommand(DAC960_Controller_T *Controller, + unsigned char *UserCommand) +{ + DAC960_Command_T *Command; + DAC960_V2_CommandMailbox_T *CommandMailbox; + ProcessorFlags_T ProcessorFlags; + unsigned char Channel, TargetID, LogicalDriveNumber; + unsigned short LogicalDeviceNumber; + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + while ((Command = DAC960_AllocateCommand(Controller)) == NULL) + DAC960_WaitForCommand(Controller); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + Controller->UserStatusLength = 0; + DAC960_V2_ClearCommand(Command); + Command->CommandType = DAC960_ImmediateCommand; + CommandMailbox = &Command->V2.CommandMailbox; + CommandMailbox->Common.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->Common.CommandControlBits.DataTransferControllerToHost = true; + CommandMailbox->Common.CommandControlBits.NoAutoRequestSense = true; + if (strcmp(UserCommand, "flush-cache") == 0) + { + CommandMailbox->DeviceOperation.IOCTL_Opcode = DAC960_V2_PauseDevice; + CommandMailbox->DeviceOperation.OperationDevice = + DAC960_V2_RAID_Controller; + DAC960_ExecuteCommand(Command); + DAC960_UserCritical("Cache Flush Completed\n", Controller); + } + else if (strncmp(UserCommand, "kill", 4) == 0 && + DAC960_ParsePhysicalDevice(Controller, &UserCommand[4], + &Channel, &TargetID) && + DAC960_V2_TranslatePhysicalDevice(Command, Channel, TargetID, + &LogicalDeviceNumber)) + { + CommandMailbox->SetDeviceState.LogicalDevice.LogicalDeviceNumber = + LogicalDeviceNumber; + CommandMailbox->SetDeviceState.IOCTL_Opcode = + DAC960_V2_SetDeviceState; + CommandMailbox->SetDeviceState.DeviceState.PhysicalDeviceState = + DAC960_V2_Device_Dead; + DAC960_ExecuteCommand(Command); + DAC960_UserCritical("Kill of Physical Device %d:%d %s\n", + Controller, Channel, TargetID, + (Command->V2.CommandStatus + == DAC960_V2_NormalCompletion + ? "Succeeded" : "Failed")); + } + else if (strncmp(UserCommand, "make-online", 11) == 0 && + DAC960_ParsePhysicalDevice(Controller, &UserCommand[11], + &Channel, &TargetID) && + DAC960_V2_TranslatePhysicalDevice(Command, Channel, TargetID, + &LogicalDeviceNumber)) + { + CommandMailbox->SetDeviceState.LogicalDevice.LogicalDeviceNumber = + LogicalDeviceNumber; + CommandMailbox->SetDeviceState.IOCTL_Opcode = + DAC960_V2_SetDeviceState; + CommandMailbox->SetDeviceState.DeviceState.PhysicalDeviceState = + DAC960_V2_Device_Online; + DAC960_ExecuteCommand(Command); + DAC960_UserCritical("Make Online of Physical Device %d:%d %s\n", + Controller, Channel, TargetID, + (Command->V2.CommandStatus + == DAC960_V2_NormalCompletion + ? "Succeeded" : "Failed")); + } + else if (strncmp(UserCommand, "make-standby", 12) == 0 && + DAC960_ParsePhysicalDevice(Controller, &UserCommand[12], + &Channel, &TargetID) && + DAC960_V2_TranslatePhysicalDevice(Command, Channel, TargetID, + &LogicalDeviceNumber)) + { + CommandMailbox->SetDeviceState.LogicalDevice.LogicalDeviceNumber = + LogicalDeviceNumber; + CommandMailbox->SetDeviceState.IOCTL_Opcode = + DAC960_V2_SetDeviceState; + CommandMailbox->SetDeviceState.DeviceState.PhysicalDeviceState = + DAC960_V2_Device_Standby; + DAC960_ExecuteCommand(Command); + DAC960_UserCritical("Make Standby of Physical Device %d:%d %s\n", + Controller, Channel, TargetID, + (Command->V2.CommandStatus + == DAC960_V2_NormalCompletion + ? "Succeeded" : "Failed")); + } + else if (strncmp(UserCommand, "rebuild", 7) == 0 && + DAC960_ParsePhysicalDevice(Controller, &UserCommand[7], + &Channel, &TargetID) && + DAC960_V2_TranslatePhysicalDevice(Command, Channel, TargetID, + &LogicalDeviceNumber)) + { + CommandMailbox->LogicalDeviceInfo.LogicalDevice.LogicalDeviceNumber = + LogicalDeviceNumber; + CommandMailbox->LogicalDeviceInfo.IOCTL_Opcode = + DAC960_V2_RebuildDeviceStart; + DAC960_ExecuteCommand(Command); + DAC960_UserCritical("Rebuild of Physical Device %d:%d %s\n", + Controller, Channel, TargetID, + (Command->V2.CommandStatus + == DAC960_V2_NormalCompletion + ? "Initiated" : "Not Initiated")); + } + else if (strncmp(UserCommand, "cancel-rebuild", 14) == 0 && + DAC960_ParsePhysicalDevice(Controller, &UserCommand[14], + &Channel, &TargetID) && + DAC960_V2_TranslatePhysicalDevice(Command, Channel, TargetID, + &LogicalDeviceNumber)) + { + CommandMailbox->LogicalDeviceInfo.LogicalDevice.LogicalDeviceNumber = + LogicalDeviceNumber; + CommandMailbox->LogicalDeviceInfo.IOCTL_Opcode = + DAC960_V2_RebuildDeviceStop; + DAC960_ExecuteCommand(Command); + DAC960_UserCritical("Rebuild of Physical Device %d:%d %s\n", + Controller, Channel, TargetID, + (Command->V2.CommandStatus + == DAC960_V2_NormalCompletion + ? "Cancelled" : "Not Cancelled")); + } + else if (strncmp(UserCommand, "check-consistency", 17) == 0 && + DAC960_ParseLogicalDrive(Controller, &UserCommand[17], + &LogicalDriveNumber)) + { + CommandMailbox->ConsistencyCheck.LogicalDevice.LogicalDeviceNumber = + LogicalDriveNumber; + CommandMailbox->ConsistencyCheck.IOCTL_Opcode = + DAC960_V2_ConsistencyCheckStart; + CommandMailbox->ConsistencyCheck.RestoreConsistency = true; + CommandMailbox->ConsistencyCheck.InitializedAreaOnly = false; + DAC960_ExecuteCommand(Command); + DAC960_UserCritical("Consistency Check of Logical Drive %d " + "(/dev/rd/c%dd%d) %s\n", + Controller, LogicalDriveNumber, + Controller->ControllerNumber, + LogicalDriveNumber, + (Command->V2.CommandStatus + == DAC960_V2_NormalCompletion + ? "Initiated" : "Not Initiated")); + } + else if (strncmp(UserCommand, "cancel-consistency-check", 24) == 0 && + DAC960_ParseLogicalDrive(Controller, &UserCommand[24], + &LogicalDriveNumber)) + { + CommandMailbox->ConsistencyCheck.LogicalDevice.LogicalDeviceNumber = + LogicalDriveNumber; + CommandMailbox->ConsistencyCheck.IOCTL_Opcode = + DAC960_V2_ConsistencyCheckStop; + DAC960_ExecuteCommand(Command); + DAC960_UserCritical("Consistency Check of Logical Drive %d " + "(/dev/rd/c%dd%d) %s\n", + Controller, LogicalDriveNumber, + Controller->ControllerNumber, + LogicalDriveNumber, + (Command->V2.CommandStatus + == DAC960_V2_NormalCompletion + ? "Cancelled" : "Not Cancelled")); + } + else DAC960_UserCritical("Illegal User Command: '%s'\n", + Controller, UserCommand); + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + DAC960_DeallocateCommand(Command); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + return true; +} + + +/* DAC960_ProcReadStatus implements reading /proc/rd/status. */ static int DAC960_ProcReadStatus(char *Page, char **Start, off_t Offset, int Count, int *EOF, void *Data) { - char *StatusMessage = "OK\n"; + unsigned char *StatusMessage = "OK\n"; int ControllerNumber, BytesAvailable; for (ControllerNumber = 0; ControllerNumber < DAC960_ControllerCount; ControllerNumber++) { DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; - DAC960_Enquiry_T *Enquiry; if (Controller == NULL) continue; - Enquiry = &Controller->Enquiry[Controller->EnquiryIndex]; - if (Enquiry->CriticalLogicalDriveCount > 0 || - Enquiry->OfflineLogicalDriveCount > 0 || - Enquiry->DeadDriveCount > 0) + if (Controller->MonitoringAlertMode) { StatusMessage = "ALERT\n"; break; @@ -3568,7 +6305,7 @@ } if (Count <= 0) return 0; *Start = Page; - memcpy(Page, &Controller->InitialStatusBuffer[Offset], Count); + memcpy(Page, &Controller->CombinedStatusBuffer[Offset], Count); return Count; } @@ -3581,6 +6318,9 @@ int Count, int *EOF, void *Data) { DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data; + unsigned char *StatusMessage = + "No Rebuild or Consistency Check in Progress\n"; + int ProgressMessageLength = strlen(StatusMessage); int BytesAvailable; if (jiffies != Controller->LastCurrentStatusTime) { @@ -3588,22 +6328,20 @@ DAC960_AnnounceDriver(Controller); DAC960_ReportControllerConfiguration(Controller); DAC960_ReportDeviceConfiguration(Controller); - Controller->CurrentStatusBuffer[Controller->CurrentStatusLength++] = ' '; - Controller->CurrentStatusBuffer[Controller->CurrentStatusLength++] = ' '; - if (Controller->RebuildProgressLength > 0) - { - strcpy(&Controller->CurrentStatusBuffer - [Controller->CurrentStatusLength], - Controller->RebuildProgressBuffer); - Controller->CurrentStatusLength += Controller->RebuildProgressLength; - } - else - { - char *StatusMessage = "No Rebuild or Consistency Check in Progress\n"; - strcpy(&Controller->CurrentStatusBuffer - [Controller->CurrentStatusLength], - StatusMessage); - Controller->CurrentStatusLength += strlen(StatusMessage); + if (Controller->ProgressBufferLength > 0) + ProgressMessageLength = Controller->ProgressBufferLength; + if (DAC960_CheckStatusBuffer(Controller, 2 + ProgressMessageLength)) + { + unsigned char *CurrentStatusBuffer = Controller->CurrentStatusBuffer; + CurrentStatusBuffer[Controller->CurrentStatusLength++] = ' '; + CurrentStatusBuffer[Controller->CurrentStatusLength++] = ' '; + if (Controller->ProgressBufferLength > 0) + strcpy(&CurrentStatusBuffer[Controller->CurrentStatusLength], + Controller->ProgressBuffer); + else + strcpy(&CurrentStatusBuffer[Controller->CurrentStatusLength], + StatusMessage); + Controller->CurrentStatusLength += ProgressMessageLength; } Controller->LastCurrentStatusTime = jiffies; } @@ -3649,7 +6387,7 @@ unsigned long Count, void *Data) { DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data; - char CommandBuffer[80]; + unsigned char CommandBuffer[80]; int Length; if (Count > sizeof(CommandBuffer)-1) return -EINVAL; copy_from_user(CommandBuffer, Buffer, Count); @@ -3657,21 +6395,25 @@ Length = strlen(CommandBuffer); if (CommandBuffer[Length-1] == '\n') CommandBuffer[--Length] = '\0'; - return (DAC960_ExecuteUserCommand(Controller, CommandBuffer) - ? Count : -EBUSY); + if (Controller->FirmwareType == DAC960_V1_Controller) + return (DAC960_V1_ExecuteUserCommand(Controller, CommandBuffer) + ? Count : -EBUSY); + else + return (DAC960_V2_ExecuteUserCommand(Controller, CommandBuffer) + ? Count : -EBUSY); } /* - DAC960_CreateProcEntries creates the /proc/driver/rd/... entries - for the DAC960 Driver. + DAC960_CreateProcEntries creates the /proc/rd/... entries for the + DAC960 Driver. */ static void DAC960_CreateProcEntries(void) { - static PROC_DirectoryEntry_T *StatusProcEntry; + PROC_DirectoryEntry_T *StatusProcEntry; int ControllerNumber; - DAC960_ProcDirectoryEntry = proc_mkdir("driver/rd", NULL); + DAC960_ProcDirectoryEntry = proc_mkdir("rd", NULL); StatusProcEntry = create_proc_read_entry("status", 0, DAC960_ProcDirectoryEntry, DAC960_ProcReadStatus, NULL); @@ -3684,29 +6426,42 @@ PROC_DirectoryEntry_T *UserCommandProcEntry; if (Controller == NULL) continue; ControllerProcEntry = proc_mkdir(Controller->ControllerName, - DAC960_ProcDirectoryEntry); - create_proc_read_entry("initial_status",0,ControllerProcEntry, + DAC960_ProcDirectoryEntry); + create_proc_read_entry("initial_status", 0, ControllerProcEntry, DAC960_ProcReadInitialStatus, Controller); - create_proc_read_entry("current_status",0,ControllerProcEntry, + create_proc_read_entry("current_status", 0, ControllerProcEntry, DAC960_ProcReadCurrentStatus, Controller); UserCommandProcEntry = - create_proc_read_entry("user_command", S_IWUSR|S_IRUSR, - ControllerProcEntry, - DAC960_ProcReadUserCommand, Controller); + create_proc_read_entry("user_command", S_IWUSR | S_IRUSR, + ControllerProcEntry, DAC960_ProcReadUserCommand, + Controller); UserCommandProcEntry->write_proc = DAC960_ProcWriteUserCommand; + Controller->ControllerProcEntry = ControllerProcEntry; } } /* - DAC960_DestroyProcEntries destroys the /proc/rd/... entries for the DAC960 - Driver. + DAC960_DestroyProcEntries destroys the /proc/rd/... entries for the + DAC960 Driver. */ static void DAC960_DestroyProcEntries(void) { - /* FIXME */ - remove_proc_entry("driver/rd", NULL); + int ControllerNumber; + for (ControllerNumber = 0; + ControllerNumber < DAC960_ControllerCount; + ControllerNumber++) + { + DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; + if (Controller == NULL) continue; + remove_proc_entry("initial_status", Controller->ControllerProcEntry); + remove_proc_entry("current_status", Controller->ControllerProcEntry); + remove_proc_entry("user_command", Controller->ControllerProcEntry); + remove_proc_entry(Controller->ControllerName, DAC960_ProcDirectoryEntry); + } + remove_proc_entry("rd/status", NULL); + remove_proc_entry("rd", NULL); } @@ -3719,18 +6474,8 @@ int init_module(void) { - int ControllerNumber; DAC960_Initialize(); - if (DAC960_ActiveControllerCount == 0) return -1; - for (ControllerNumber = 0; - ControllerNumber < DAC960_ControllerCount; - ControllerNumber++) - { - DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL) continue; - DAC960_InitializeGenericDiskInfo(&Controller->GenericDiskInfo); - } - return 0; + return (DAC960_ActiveControllerCount > 0 ? 0 : -1); } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/block/DAC960.h linux/drivers/block/DAC960.h --- v2.4.0-test5/linux/drivers/block/DAC960.h Tue May 23 15:31:34 2000 +++ linux/drivers/block/DAC960.h Fri Aug 4 13:11:00 2000 @@ -1,8 +1,8 @@ /* - Linux Driver for Mylex DAC960 and DAC1100 PCI RAID Controllers + Linux Driver for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers - Copyright 1998-1999 by Leonard N. Zubkoff + Copyright 1998-2000 by Leonard N. Zubkoff This program is free software; you may redistribute and/or modify it under the terms of the GNU General Public License Version 2 as published by the @@ -27,27 +27,41 @@ /* - Define the maximum number of Controller Channels supported by this driver. + Define the maximum number of Controller Channels supported by DAC960 + V1 and V2 Firmware Controllers. */ -#define DAC960_MaxChannels 3 +#define DAC960_V1_MaxChannels 3 +#define DAC960_V2_MaxChannels 4 /* - Define the maximum number of Targets per Channel supported by this driver. + Define the maximum number of Targets per Channel supported by DAC960 + V1 and V2 Firmware Controllers. */ -#define DAC960_MaxTargets 16 +#define DAC960_V1_MaxTargets 16 +#define DAC960_V2_MaxTargets 128 /* - Define the maximum number of Logical Drives supported by any DAC960 model. + Define the maximum number of Logical Drives supported by DAC960 + V1 and V2 Firmware Controllers. */ #define DAC960_MaxLogicalDrives 32 /* + Define the maximum number of Physical Devices supported by DAC960 + V1 and V2 Firmware Controllers. +*/ + +#define DAC960_V1_MaxPhysicalDevices 45 +#define DAC960_V2_MaxPhysicalDevices 272 + + +/* Define a Boolean data type. */ @@ -72,149 +86,264 @@ Define a 32 bit Bus Address data type. */ -typedef unsigned int DAC960_BusAddress_T; +typedef unsigned int DAC960_BusAddress32_T; + + +/* + Define a 64 bit Bus Address data type. +*/ + +typedef unsigned long long DAC960_BusAddress64_T; /* Define a 32 bit Byte Count data type. */ -typedef unsigned int DAC960_ByteCount_T; +typedef unsigned int DAC960_ByteCount32_T; + + +/* + Define a 64 bit Byte Count data type. +*/ + +typedef unsigned long long DAC960_ByteCount64_T; + + +/* + Define the SCSI INQUIRY Standard Data structure. +*/ + +typedef struct DAC960_SCSI_Inquiry +{ + unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */ + unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */ + unsigned char DeviceTypeModifier:7; /* Byte 1 Bits 0-6 */ + boolean RMB:1; /* Byte 1 Bit 7 */ + unsigned char ANSI_ApprovedVersion:3; /* Byte 2 Bits 0-2 */ + unsigned char ECMA_Version:3; /* Byte 2 Bits 3-5 */ + unsigned char ISO_Version:2; /* Byte 2 Bits 6-7 */ + unsigned char ResponseDataFormat:4; /* Byte 3 Bits 0-3 */ + unsigned char :2; /* Byte 3 Bits 4-5 */ + boolean TrmIOP:1; /* Byte 3 Bit 6 */ + boolean AENC:1; /* Byte 3 Bit 7 */ + unsigned char AdditionalLength; /* Byte 4 */ + unsigned char :8; /* Byte 5 */ + unsigned char :8; /* Byte 6 */ + boolean SftRe:1; /* Byte 7 Bit 0 */ + boolean CmdQue:1; /* Byte 7 Bit 1 */ + boolean :1; /* Byte 7 Bit 2 */ + boolean Linked:1; /* Byte 7 Bit 3 */ + boolean Sync:1; /* Byte 7 Bit 4 */ + boolean WBus16:1; /* Byte 7 Bit 5 */ + boolean WBus32:1; /* Byte 7 Bit 6 */ + boolean RelAdr:1; /* Byte 7 Bit 7 */ + unsigned char VendorIdentification[8]; /* Bytes 8-15 */ + unsigned char ProductIdentification[16]; /* Bytes 16-31 */ + unsigned char ProductRevisionLevel[4]; /* Bytes 32-35 */ +} +DAC960_SCSI_Inquiry_T; + + +/* + Define the SCSI INQUIRY Unit Serial Number structure. +*/ + +typedef struct DAC960_SCSI_Inquiry_UnitSerialNumber +{ + unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */ + unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */ + unsigned char PageCode; /* Byte 1 */ + unsigned char :8; /* Byte 2 */ + unsigned char PageLength; /* Byte 3 */ + unsigned char ProductSerialNumber[28]; /* Bytes 4-31 */ +} +DAC960_SCSI_Inquiry_UnitSerialNumber_T; + + +/* + Define the SCSI REQUEST SENSE Sense Key type. +*/ + +typedef enum +{ + DAC960_SenseKey_NoSense = 0x0, + DAC960_SenseKey_RecoveredError = 0x1, + DAC960_SenseKey_NotReady = 0x2, + DAC960_SenseKey_MediumError = 0x3, + DAC960_SenseKey_HardwareError = 0x4, + DAC960_SenseKey_IllegalRequest = 0x5, + DAC960_SenseKey_UnitAttention = 0x6, + DAC960_SenseKey_DataProtect = 0x7, + DAC960_SenseKey_BlankCheck = 0x8, + DAC960_SenseKey_VendorSpecific = 0x9, + DAC960_SenseKey_CopyAborted = 0xA, + DAC960_SenseKey_AbortedCommand = 0xB, + DAC960_SenseKey_Equal = 0xC, + DAC960_SenseKey_VolumeOverflow = 0xD, + DAC960_SenseKey_Miscompare = 0xE, + DAC960_SenseKey_Reserved = 0xF +} +__attribute__ ((packed)) +DAC960_SCSI_RequestSenseKey_T; + + +/* + Define the SCSI REQUEST SENSE structure. +*/ + +typedef struct DAC960_SCSI_RequestSense +{ + unsigned char ErrorCode:7; /* Byte 0 Bits 0-6 */ + boolean Valid:1; /* Byte 0 Bit 7 */ + unsigned char SegmentNumber; /* Byte 1 */ + DAC960_SCSI_RequestSenseKey_T SenseKey:4; /* Byte 2 Bits 0-3 */ + unsigned char :1; /* Byte 2 Bit 4 */ + boolean ILI:1; /* Byte 2 Bit 5 */ + boolean EOM:1; /* Byte 2 Bit 6 */ + boolean Filemark:1; /* Byte 2 Bit 7 */ + unsigned char Information[4]; /* Bytes 3-6 */ + unsigned char AdditionalSenseLength; /* Byte 7 */ + unsigned char CommandSpecificInformation[4]; /* Bytes 8-11 */ + unsigned char AdditionalSenseCode; /* Byte 12 */ + unsigned char AdditionalSenseCodeQualifier; /* Byte 13 */ +} +DAC960_SCSI_RequestSense_T; /* - Define the DAC960 Command Opcodes. + Define the DAC960 V1 Firmware Command Opcodes. */ typedef enum { /* I/O Commands */ - DAC960_ReadExtended = 0x33, - DAC960_WriteExtended = 0x34, - DAC960_ReadAheadExtended = 0x35, - DAC960_ReadExtendedWithScatterGather = 0xB3, - DAC960_WriteExtendedWithScatterGather = 0xB4, - DAC960_Read = 0x36, - DAC960_ReadWithOldScatterGather = 0xB6, - DAC960_Write = 0x37, - DAC960_WriteWithOldScatterGather = 0xB7, - DAC960_DCDB = 0x04, - DAC960_DCDBWithScatterGather = 0x84, - DAC960_Flush = 0x0A, + DAC960_V1_ReadExtended = 0x33, + DAC960_V1_WriteExtended = 0x34, + DAC960_V1_ReadAheadExtended = 0x35, + DAC960_V1_ReadExtendedWithScatterGather = 0xB3, + DAC960_V1_WriteExtendedWithScatterGather = 0xB4, + DAC960_V1_Read = 0x36, + DAC960_V1_ReadWithOldScatterGather = 0xB6, + DAC960_V1_Write = 0x37, + DAC960_V1_WriteWithOldScatterGather = 0xB7, + DAC960_V1_DCDB = 0x04, + DAC960_V1_DCDBWithScatterGather = 0x84, + DAC960_V1_Flush = 0x0A, /* Controller Status Related Commands */ - DAC960_Enquiry = 0x53, - DAC960_Enquiry2 = 0x1C, - DAC960_GetLogicalDriveElement = 0x55, - DAC960_GetLogicalDriveInformation = 0x19, - DAC960_IOPortRead = 0x39, - DAC960_IOPortWrite = 0x3A, - DAC960_GetSDStats = 0x3E, - DAC960_GetPDStats = 0x3F, - DAC960_PerformEventLogOperation = 0x72, + DAC960_V1_Enquiry = 0x53, + DAC960_V1_Enquiry2 = 0x1C, + DAC960_V1_GetLogicalDriveElement = 0x55, + DAC960_V1_GetLogicalDriveInformation = 0x19, + DAC960_V1_IOPortRead = 0x39, + DAC960_V1_IOPortWrite = 0x3A, + DAC960_V1_GetSDStats = 0x3E, + DAC960_V1_GetPDStats = 0x3F, + DAC960_V1_PerformEventLogOperation = 0x72, /* Device Related Commands */ - DAC960_StartDevice = 0x10, - DAC960_GetDeviceState = 0x50, - DAC960_StopChannel = 0x13, - DAC960_StartChannel = 0x12, - DAC960_ResetChannel = 0x1A, + DAC960_V1_StartDevice = 0x10, + DAC960_V1_GetDeviceState = 0x50, + DAC960_V1_StopChannel = 0x13, + DAC960_V1_StartChannel = 0x12, + DAC960_V1_ResetChannel = 0x1A, /* Commands Associated with Data Consistency and Errors */ - DAC960_Rebuild = 0x09, - DAC960_RebuildAsync = 0x16, - DAC960_CheckConsistency = 0x0F, - DAC960_CheckConsistencyAsync = 0x1E, - DAC960_RebuildStat = 0x0C, - DAC960_GetRebuildProgress = 0x27, - DAC960_RebuildControl = 0x1F, - DAC960_ReadBadBlockTable = 0x0B, - DAC960_ReadBadDataTable = 0x25, - DAC960_ClearBadDataTable = 0x26, - DAC960_GetErrorTable = 0x17, - DAC960_AddCapacityAsync = 0x2A, + DAC960_V1_Rebuild = 0x09, + DAC960_V1_RebuildAsync = 0x16, + DAC960_V1_CheckConsistency = 0x0F, + DAC960_V1_CheckConsistencyAsync = 0x1E, + DAC960_V1_RebuildStat = 0x0C, + DAC960_V1_GetRebuildProgress = 0x27, + DAC960_V1_RebuildControl = 0x1F, + DAC960_V1_ReadBadBlockTable = 0x0B, + DAC960_V1_ReadBadDataTable = 0x25, + DAC960_V1_ClearBadDataTable = 0x26, + DAC960_V1_GetErrorTable = 0x17, + DAC960_V1_AddCapacityAsync = 0x2A, /* Configuration Related Commands */ - DAC960_ReadConfig2 = 0x3D, - DAC960_WriteConfig2 = 0x3C, - DAC960_ReadConfigurationOnDisk = 0x4A, - DAC960_WriteConfigurationOnDisk = 0x4B, - DAC960_ReadConfiguration = 0x4E, - DAC960_ReadBackupConfiguration = 0x4D, - DAC960_WriteConfiguration = 0x4F, - DAC960_AddConfiguration = 0x4C, - DAC960_ReadConfigurationLabel = 0x48, - DAC960_WriteConfigurationLabel = 0x49, + DAC960_V1_ReadConfig2 = 0x3D, + DAC960_V1_WriteConfig2 = 0x3C, + DAC960_V1_ReadConfigurationOnDisk = 0x4A, + DAC960_V1_WriteConfigurationOnDisk = 0x4B, + DAC960_V1_ReadConfiguration = 0x4E, + DAC960_V1_ReadBackupConfiguration = 0x4D, + DAC960_V1_WriteConfiguration = 0x4F, + DAC960_V1_AddConfiguration = 0x4C, + DAC960_V1_ReadConfigurationLabel = 0x48, + DAC960_V1_WriteConfigurationLabel = 0x49, /* Firmware Upgrade Related Commands */ - DAC960_LoadImage = 0x20, - DAC960_StoreImage = 0x21, - DAC960_ProgramImage = 0x22, + DAC960_V1_LoadImage = 0x20, + DAC960_V1_StoreImage = 0x21, + DAC960_V1_ProgramImage = 0x22, /* Diagnostic Commands */ - DAC960_SetDiagnosticMode = 0x31, - DAC960_RunDiagnostic = 0x32, + DAC960_V1_SetDiagnosticMode = 0x31, + DAC960_V1_RunDiagnostic = 0x32, /* Subsystem Service Commands */ - DAC960_GetSubsystemData = 0x70, - DAC960_SetSubsystemParameters = 0x71 + DAC960_V1_GetSubsystemData = 0x70, + DAC960_V1_SetSubsystemParameters = 0x71 } __attribute__ ((packed)) -DAC960_CommandOpcode_T; +DAC960_V1_CommandOpcode_T; /* - Define the DAC960 Command Identifier type. + Define the DAC960 V1 Firmware Command Identifier type. */ -typedef unsigned char DAC960_CommandIdentifier_T; +typedef unsigned char DAC960_V1_CommandIdentifier_T; /* - Define the DAC960 Command Status Codes. + Define the DAC960 V1 Firmware Command Status Codes. */ -#define DAC960_NormalCompletion 0x0000 /* Common */ -#define DAC960_CheckConditionReceived 0x0002 /* Common */ -#define DAC960_NoDeviceAtAddress 0x0102 /* Common */ -#define DAC960_InvalidDeviceAddress 0x0105 /* Common */ -#define DAC960_InvalidParameter 0x0105 /* Common */ -#define DAC960_IrrecoverableDataError 0x0001 /* I/O */ -#define DAC960_LogicalDriveNonexistentOrOffline 0x0002 /* I/O */ -#define DAC960_AccessBeyondEndOfLogicalDrive 0x0105 /* I/O */ -#define DAC960_BadDataEncountered 0x010C /* I/O */ -#define DAC960_DeviceBusy 0x0008 /* DCDB */ -#define DAC960_DeviceNonresponsive 0x000E /* DCDB */ -#define DAC960_CommandTerminatedAbnormally 0x000F /* DCDB */ -#define DAC960_UnableToStartDevice 0x0002 /* Device */ -#define DAC960_InvalidChannelOrTargetOrModifier 0x0105 /* Device */ -#define DAC960_ChannelBusy 0x0106 /* Device */ -#define DAC960_ChannelNotStopped 0x0002 /* Device */ -#define DAC960_AttemptToRebuildOnlineDrive 0x0002 /* Consistency */ -#define DAC960_RebuildBadBlocksEncountered 0x0003 /* Consistency */ -#define DAC960_NewDiskFailedDuringRebuild 0x0004 /* Consistency */ -#define DAC960_RebuildOrCheckAlreadyInProgress 0x0106 /* Consistency */ -#define DAC960_DependentDiskIsDead 0x0002 /* Consistency */ -#define DAC960_InconsistentBlocksFound 0x0003 /* Consistency */ -#define DAC960_InvalidOrNonredundantLogicalDrive 0x0105 /* Consistency */ -#define DAC960_NoRebuildOrCheckInProgress 0x0105 /* Consistency */ -#define DAC960_RebuildInProgress_DataValid 0x0000 /* Consistency */ -#define DAC960_RebuildFailed_LogicalDriveFailure 0x0002 /* Consistency */ -#define DAC960_RebuildFailed_BadBlocksOnOther 0x0003 /* Consistency */ -#define DAC960_RebuildFailed_NewDriveFailed 0x0004 /* Consistency */ -#define DAC960_RebuildSuccessful 0x0100 /* Consistency */ -#define DAC960_RebuildSuccessfullyTerminated 0x0107 /* Consistency */ -#define DAC960_AddCapacityInProgress 0x0004 /* Consistency */ -#define DAC960_AddCapacityFailedOrSuspended 0x00F4 /* Consistency */ -#define DAC960_Config2ChecksumError 0x0002 /* Configuration */ -#define DAC960_ConfigurationSuspended 0x0106 /* Configuration */ -#define DAC960_FailedToConfigureNVRAM 0x0105 /* Configuration */ -#define DAC960_ConfigurationNotSavedStateChange 0x0106 /* Configuration */ -#define DAC960_SubsystemNotInstalled 0x0001 /* Subsystem */ -#define DAC960_SubsystemFailed 0x0002 /* Subsystem */ -#define DAC960_SubsystemBusy 0x0106 /* Subsystem */ +#define DAC960_V1_NormalCompletion 0x0000 /* Common */ +#define DAC960_V1_CheckConditionReceived 0x0002 /* Common */ +#define DAC960_V1_NoDeviceAtAddress 0x0102 /* Common */ +#define DAC960_V1_InvalidDeviceAddress 0x0105 /* Common */ +#define DAC960_V1_InvalidParameter 0x0105 /* Common */ +#define DAC960_V1_IrrecoverableDataError 0x0001 /* I/O */ +#define DAC960_V1_LogicalDriveNonexistentOrOffline 0x0002 /* I/O */ +#define DAC960_V1_AccessBeyondEndOfLogicalDrive 0x0105 /* I/O */ +#define DAC960_V1_BadDataEncountered 0x010C /* I/O */ +#define DAC960_V1_DeviceBusy 0x0008 /* DCDB */ +#define DAC960_V1_DeviceNonresponsive 0x000E /* DCDB */ +#define DAC960_V1_CommandTerminatedAbnormally 0x000F /* DCDB */ +#define DAC960_V1_UnableToStartDevice 0x0002 /* Device */ +#define DAC960_V1_InvalidChannelOrTargetOrModifier 0x0105 /* Device */ +#define DAC960_V1_ChannelBusy 0x0106 /* Device */ +#define DAC960_V1_ChannelNotStopped 0x0002 /* Device */ +#define DAC960_V1_AttemptToRebuildOnlineDrive 0x0002 /* Consistency */ +#define DAC960_V1_RebuildBadBlocksEncountered 0x0003 /* Consistency */ +#define DAC960_V1_NewDiskFailedDuringRebuild 0x0004 /* Consistency */ +#define DAC960_V1_RebuildOrCheckAlreadyInProgress 0x0106 /* Consistency */ +#define DAC960_V1_DependentDiskIsDead 0x0002 /* Consistency */ +#define DAC960_V1_InconsistentBlocksFound 0x0003 /* Consistency */ +#define DAC960_V1_InvalidOrNonredundantLogicalDrive 0x0105 /* Consistency */ +#define DAC960_V1_NoRebuildOrCheckInProgress 0x0105 /* Consistency */ +#define DAC960_V1_RebuildInProgress_DataValid 0x0000 /* Consistency */ +#define DAC960_V1_RebuildFailed_LogicalDriveFailure 0x0002 /* Consistency */ +#define DAC960_V1_RebuildFailed_BadBlocksOnOther 0x0003 /* Consistency */ +#define DAC960_V1_RebuildFailed_NewDriveFailed 0x0004 /* Consistency */ +#define DAC960_V1_RebuildSuccessful 0x0100 /* Consistency */ +#define DAC960_V1_RebuildSuccessfullyTerminated 0x0107 /* Consistency */ +#define DAC960_V1_AddCapacityInProgress 0x0004 /* Consistency */ +#define DAC960_V1_AddCapacityFailedOrSuspended 0x00F4 /* Consistency */ +#define DAC960_V1_Config2ChecksumError 0x0002 /* Configuration */ +#define DAC960_V1_ConfigurationSuspended 0x0106 /* Configuration */ +#define DAC960_V1_FailedToConfigureNVRAM 0x0105 /* Configuration */ +#define DAC960_V1_ConfigurationNotSavedStateChange 0x0106 /* Configuration */ +#define DAC960_V1_SubsystemNotInstalled 0x0001 /* Subsystem */ +#define DAC960_V1_SubsystemFailed 0x0002 /* Subsystem */ +#define DAC960_V1_SubsystemBusy 0x0106 /* Subsystem */ -typedef unsigned short DAC960_CommandStatus_T; +typedef unsigned short DAC960_V1_CommandStatus_T; /* - Define the Enquiry reply structure. + Define the DAC960 V1 Firmware Enquiry Command reply structure. */ -typedef struct DAC960_Enquiry +typedef struct DAC960_V1_Enquiry { unsigned char NumberOfLogicalDrives; /* Byte 0 */ unsigned int :24; /* Bytes 1-3 */ @@ -229,15 +358,15 @@ unsigned char MinorFirmwareVersion; /* Byte 136 */ unsigned char MajorFirmwareVersion; /* Byte 137 */ enum { - DAC960_NoStandbyRebuildOrCheckInProgress = 0x00, - DAC960_StandbyRebuildInProgress = 0x01, - DAC960_BackgroundRebuildInProgress = 0x02, - DAC960_BackgroundCheckInProgress = 0x03, - DAC960_StandbyRebuildCompletedWithError = 0xFF, - DAC960_BackgroundRebuildOrCheckFailed_DriveFailed = 0xF0, - DAC960_BackgroundRebuildOrCheckFailed_LogicalDriveFailed = 0xF1, - DAC960_BackgroundRebuildOrCheckFailed_OtherCauses = 0xF2, - DAC960_BackgroundRebuildOrCheckSuccessfullyTerminated = 0xF3 + DAC960_V1_NoStandbyRebuildOrCheckInProgress = 0x00, + DAC960_V1_StandbyRebuildInProgress = 0x01, + DAC960_V1_BackgroundRebuildInProgress = 0x02, + DAC960_V1_BackgroundCheckInProgress = 0x03, + DAC960_V1_StandbyRebuildCompletedWithError = 0xFF, + DAC960_V1_BackgroundRebuildOrCheckFailed_DriveFailed = 0xF0, + DAC960_V1_BackgroundRebuildOrCheckFailed_LogicalDriveFailed = 0xF1, + DAC960_V1_BackgroundRebuildOrCheckFailed_OtherCauses = 0xF2, + DAC960_V1_BackgroundRebuildOrCheckSuccessfullyTerminated = 0xF3 } __attribute__ ((packed)) RebuildFlag; /* Byte 138 */ unsigned char MaxCommands; /* Byte 139 */ unsigned char OfflineLogicalDriveCount; /* Byte 140 */ @@ -261,40 +390,40 @@ unsigned char Reserved[62]; /* Bytes 195-255 */ } __attribute__ ((packed)) -DAC960_Enquiry_T; +DAC960_V1_Enquiry_T; /* - Define the Enquiry2 reply structure. + Define the DAC960 V1 Firmware Enquiry2 Command reply structure. */ -typedef struct DAC960_Enquiry2 +typedef struct DAC960_V1_Enquiry2 { struct { enum { - DAC960_P_PD_PU = 0x01, - DAC960_PL = 0x02, - DAC960_PG = 0x10, - DAC960_PJ = 0x11, - DAC960_PR = 0x12, - DAC960_PT = 0x13, - DAC960_PTL0 = 0x14, - DAC960_PRL = 0x15, - DAC960_PTL1 = 0x16, - DAC1164_P = 0x20 + DAC960_V1_P_PD_PU = 0x01, + DAC960_V1_PL = 0x02, + DAC960_V1_PG = 0x10, + DAC960_V1_PJ = 0x11, + DAC960_V1_PR = 0x12, + DAC960_V1_PT = 0x13, + DAC960_V1_PTL0 = 0x14, + DAC960_V1_PRL = 0x15, + DAC960_V1_PTL1 = 0x16, + DAC960_V1_1164P = 0x20 } __attribute__ ((packed)) SubModel; /* Byte 0 */ unsigned char ActualChannels; /* Byte 1 */ enum { - DAC960_FiveChannelBoard = 0x01, - DAC960_ThreeChannelBoard = 0x02, - DAC960_TwoChannelBoard = 0x03, - DAC960_ThreeChannelASIC_DAC = 0x04 + DAC960_V1_FiveChannelBoard = 0x01, + DAC960_V1_ThreeChannelBoard = 0x02, + DAC960_V1_TwoChannelBoard = 0x03, + DAC960_V1_ThreeChannelASIC_DAC = 0x04 } __attribute__ ((packed)) Model; /* Byte 2 */ enum { - DAC960_EISA_Controller = 0x01, - DAC960_MicroChannel_Controller = 0x02, - DAC960_PCI_Controller = 0x03, - DAC960_SCSItoSCSI_Controller = 0x08 + DAC960_V1_EISA_Controller = 0x01, + DAC960_V1_MicroChannel_Controller = 0x02, + DAC960_V1_PCI_Controller = 0x03, + DAC960_V1_SCSItoSCSI_Controller = 0x08 } __attribute__ ((packed)) ProductFamily; /* Byte 3 */ } HardwareID; /* Bytes 0-3 */ /* MajorVersion.MinorVersion-FirmwareType-TurnID */ @@ -321,14 +450,14 @@ unsigned int NonVolatileMemorySize; /* Bytes 36-39 */ struct { enum { - DAC960_DRAM = 0x00, - DAC960_EDO = 0x01, - DAC960_SDRAM = 0x02 + DAC960_V1_DRAM = 0x0, + DAC960_V1_EDO = 0x1, + DAC960_V1_SDRAM = 0x2 } __attribute__ ((packed)) RamType:3; /* Byte 40 Bits 0-2 */ enum { - DAC960_None = 0x00, - DAC960_Parity = 0x01, - DAC960_ECC = 0x02 + DAC960_V1_None = 0x0, + DAC960_V1_Parity = 0x1, + DAC960_V1_ECC = 0x2 } __attribute__ ((packed)) ErrorCorrection:3; /* Byte 40 Bits 3-5 */ boolean FastPageMode:1; /* Byte 40 Bit 6 */ boolean LowPowerMemory:1; /* Byte 40 Bit 7 */ @@ -367,14 +496,14 @@ unsigned short CacheLineSize; /* Bytes 104-105 */ struct { enum { - DAC960_Narrow_8bit = 0x00, - DAC960_Wide_16bit = 0x01, - DAC960_Wide_32bit = 0x02 + DAC960_V1_Narrow_8bit = 0x0, + DAC960_V1_Wide_16bit = 0x1, + DAC960_V1_Wide_32bit = 0x2 } __attribute__ ((packed)) BusWidth:2; /* Byte 106 Bits 0-1 */ enum { - DAC960_Fast = 0x00, - DAC960_Ultra = 0x01, - DAC960_Ultra2 = 0x02 + DAC960_V1_Fast = 0x0, + DAC960_V1_Ultra = 0x1, + DAC960_V1_Ultra2 = 0x2 } __attribute__ ((packed)) BusSpeed:2; /* Byte 106 Bits 2-3 */ boolean Differential:1; /* Byte 106 Bit 4 */ unsigned char :3; /* Byte 106 Bits 5-7 */ @@ -383,12 +512,12 @@ unsigned int :32; /* Bytes 108-111 */ unsigned short FirmwareBuildNumber; /* Bytes 112-113 */ enum { - DAC960_AEMI = 0x01, - DAC960_OEM1 = 0x02, - DAC960_OEM2 = 0x04, - DAC960_OEM3 = 0x08, - DAC960_Conner = 0x10, - DAC960_SAFTE = 0x20 + DAC960_V1_AEMI = 0x01, + DAC960_V1_OEM1 = 0x02, + DAC960_V1_OEM2 = 0x04, + DAC960_V1_OEM3 = 0x08, + DAC960_V1_Conner = 0x10, + DAC960_V1_SAFTE = 0x20 } __attribute__ ((packed)) FaultManagementType; /* Byte 114 */ unsigned char :8; /* Byte 115 */ struct { @@ -399,55 +528,64 @@ unsigned int :32; /* Bytes 120-123 */ unsigned int :32; /* Bytes 124-127 */ } -DAC960_Enquiry2_T; +DAC960_V1_Enquiry2_T; /* - Define the Logical Drive State type. + Define the DAC960 V1 Firmware Logical Drive State type. */ typedef enum { - DAC960_LogicalDrive_Online = 0x03, - DAC960_LogicalDrive_Critical = 0x04, - DAC960_LogicalDrive_Offline = 0xFF + DAC960_V1_LogicalDrive_Online = 0x03, + DAC960_V1_LogicalDrive_Critical = 0x04, + DAC960_V1_LogicalDrive_Offline = 0xFF } __attribute__ ((packed)) -DAC960_LogicalDriveState_T; +DAC960_V1_LogicalDriveState_T; /* - Define the Get Logical Drive Information reply structure. + Define the DAC960 V1 Firmware Logical Drive Information structure. */ -typedef struct DAC960_LogicalDriveInformation +typedef struct DAC960_V1_LogicalDriveInformation { unsigned int LogicalDriveSize; /* Bytes 0-3 */ - DAC960_LogicalDriveState_T LogicalDriveState; /* Byte 4 */ + DAC960_V1_LogicalDriveState_T LogicalDriveState; /* Byte 4 */ unsigned char RAIDLevel:7; /* Byte 5 Bits 0-6 */ boolean WriteBack:1; /* Byte 5 Bit 7 */ - unsigned int :16; /* Bytes 6-7 */ + unsigned short :16; /* Bytes 6-7 */ } -DAC960_LogicalDriveInformation_T; +DAC960_V1_LogicalDriveInformation_T; + + +/* + Define the DAC960 V1 Firmware Get Logical Drive Information Command + reply structure. +*/ + +typedef DAC960_V1_LogicalDriveInformation_T + DAC960_V1_LogicalDriveInformationArray_T[DAC960_MaxLogicalDrives]; /* - Define the Perform Event Log Operation Types. + Define the DAC960 V1 Firmware Perform Event Log Operation Types. */ typedef enum { - DAC960_GetEventLogEntry = 0x00 + DAC960_V1_GetEventLogEntry = 0x00 } __attribute__ ((packed)) -DAC960_PerformEventLogOpType_T; +DAC960_V1_PerformEventLogOpType_T; /* - Define the Get Event Log Entry reply structure. + Define the DAC960 V1 Firmware Get Event Log Entry Command reply structure. */ -typedef struct DAC960_EventLogEntry +typedef struct DAC960_V1_EventLogEntry { unsigned char MessageType; /* Byte 0 */ unsigned char MessageLength; /* Byte 1 */ @@ -459,7 +597,7 @@ unsigned char ErrorCode:7; /* Byte 6 Bits 0-6 */ boolean Valid:1; /* Byte 6 Bit 7 */ unsigned char SegmentNumber; /* Byte 7 */ - unsigned char SenseKey:4; /* Byte 8 Bits 0-3 */ + DAC960_SCSI_RequestSenseKey_T SenseKey:4; /* Byte 8 Bits 0-3 */ unsigned char :1; /* Byte 8 Bit 4 */ boolean ILI:1; /* Byte 8 Bit 5 */ boolean EOM:1; /* Byte 8 Bit 6 */ @@ -471,37 +609,37 @@ unsigned char AdditionalSenseCodeQualifier; /* Byte 19 */ unsigned char Dummy[12]; /* Bytes 20-31 */ } -DAC960_EventLogEntry_T; +DAC960_V1_EventLogEntry_T; /* - Define the Physical Device State type. + Define the DAC960 V1 Firmware Physical Device State type. */ typedef enum { - DAC960_Device_Dead = 0x00, - DAC960_Device_WriteOnly = 0x02, - DAC960_Device_Online = 0x03, - DAC960_Device_Standby = 0x10 + DAC960_V1_Device_Dead = 0x00, + DAC960_V1_Device_WriteOnly = 0x02, + DAC960_V1_Device_Online = 0x03, + DAC960_V1_Device_Standby = 0x10 } __attribute__ ((packed)) -DAC960_PhysicalDeviceState_T; +DAC960_V1_PhysicalDeviceState_T; /* - Define the Get Device State reply structure. + Define the DAC960 V1 Firmware Get Device State Command reply structure. */ -typedef struct DAC960_DeviceState +typedef struct DAC960_V1_DeviceState { boolean Present:1; /* Byte 0 Bit 0 */ unsigned char :7; /* Byte 0 Bits 1-7 */ enum { - DAC960_OtherType = 0x00, - DAC960_DiskType = 0x01, - DAC960_SequentialType = 0x02, - DAC960_CDROM_or_WORM_Type = 0x03 + DAC960_V1_OtherType = 0x0, + DAC960_V1_DiskType = 0x1, + DAC960_V1_SequentialType = 0x2, + DAC960_V1_CDROM_or_WORM_Type = 0x3 } __attribute__ ((packed)) DeviceType:2; /* Byte 1 Bits 0-1 */ boolean :1; /* Byte 1 Bit 2 */ boolean Fast20:1; /* Byte 1 Bit 3 */ @@ -509,60 +647,60 @@ boolean Fast:1; /* Byte 1 Bit 5 */ boolean Wide:1; /* Byte 1 Bit 6 */ boolean TaggedQueuingSupported:1; /* Byte 1 Bit 7 */ - DAC960_PhysicalDeviceState_T DeviceState; /* Byte 2 */ + DAC960_V1_PhysicalDeviceState_T DeviceState; /* Byte 2 */ unsigned char :8; /* Byte 3 */ unsigned char SynchronousMultiplier; /* Byte 4 */ unsigned char SynchronousOffset:5; /* Byte 5 Bits 0-4 */ unsigned char :3; /* Byte 5 Bits 5-7 */ unsigned int DiskSize __attribute__ ((packed)); /* Bytes 6-9 */ } -DAC960_DeviceState_T; +DAC960_V1_DeviceState_T; /* - Define the Get Rebuild Progress reply structure. + Define the DAC960 V1 Firmware Get Rebuild Progress Command reply structure. */ -typedef struct DAC960_RebuildProgress +typedef struct DAC960_V1_RebuildProgress { unsigned int LogicalDriveNumber; /* Bytes 0-3 */ unsigned int LogicalDriveSize; /* Bytes 4-7 */ unsigned int RemainingBlocks; /* Bytes 8-11 */ } -DAC960_RebuildProgress_T; +DAC960_V1_RebuildProgress_T; /* - Define the Error Table Entry and Get Error Table reply structure. + Define the DAC960 V1 Firmware Error Table Entry structure. */ -typedef struct DAC960_ErrorTableEntry +typedef struct DAC960_V1_ErrorTableEntry { unsigned char ParityErrorCount; /* Byte 0 */ unsigned char SoftErrorCount; /* Byte 1 */ unsigned char HardErrorCount; /* Byte 2 */ unsigned char MiscErrorCount; /* Byte 3 */ } -DAC960_ErrorTableEntry_T; +DAC960_V1_ErrorTableEntry_T; /* - Define the Get Error Table reply structure. + Define the DAC960 V1 Firmware Get Error Table Command reply structure. */ -typedef struct DAC960_ErrorTable +typedef struct DAC960_V1_ErrorTable { - DAC960_ErrorTableEntry_T - ErrorTableEntries[DAC960_MaxChannels][DAC960_MaxTargets]; + DAC960_V1_ErrorTableEntry_T + ErrorTableEntries[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets]; } -DAC960_ErrorTable_T; +DAC960_V1_ErrorTable_T; /* - Define the Config2 reply structure. + Define the DAC960 V1 Firmware Read Config2 Command reply structure. */ -typedef struct DAC960_Config2 +typedef struct DAC960_V1_Config2 { unsigned char :1; /* Byte 0 Bit 0 */ boolean ActiveNegationEnabled:1; /* Byte 0 Bit 1 */ @@ -576,12 +714,12 @@ boolean AEMI_OFM:1; /* Byte 1 Bit 6 */ unsigned char :1; /* Byte 1 Bit 7 */ enum { - DAC960_OEMID_Mylex = 0x00, - DAC960_OEMID_IBM = 0x08, - DAC960_OEMID_HP = 0x0A, - DAC960_OEMID_DEC = 0x0C, - DAC960_OEMID_Siemens = 0x10, - DAC960_OEMID_Intel = 0x12 + DAC960_V1_OEMID_Mylex = 0x00, + DAC960_V1_OEMID_IBM = 0x08, + DAC960_V1_OEMID_HP = 0x0A, + DAC960_V1_OEMID_DEC = 0x0C, + DAC960_V1_OEMID_Siemens = 0x10, + DAC960_V1_OEMID_Intel = 0x12 } __attribute__ ((packed)) OEMID; /* Byte 2 */ unsigned char OEMModelNumber; /* Byte 3 */ unsigned char PhysicalSector; /* Byte 4 */ @@ -600,21 +738,21 @@ unsigned char BlocksPerStripe; /* Byte 11 */ struct { enum { - DAC960_Async = 0x00, - DAC960_Sync_8MHz = 0x01, - DAC960_Sync_5MHz = 0x02, - DAC960_Sync_10or20MHz = 0x03 /* Bits 0-1 */ + DAC960_V1_Async = 0x0, + DAC960_V1_Sync_8MHz = 0x1, + DAC960_V1_Sync_5MHz = 0x2, + DAC960_V1_Sync_10or20MHz = 0x3 /* Byte 11 Bits 0-1 */ } __attribute__ ((packed)) Speed:2; - boolean Force8Bit:1; /* Bit 2 */ - boolean DisableFast20:1; /* Bit 3 */ - unsigned char :3; /* Bits 4-6 */ - boolean EnableTaggedQueuing:1; /* Bit 7 */ + boolean Force8Bit:1; /* Byte 11 Bit 2 */ + boolean DisableFast20:1; /* Byte 11 Bit 3 */ + unsigned char :3; /* Byte 11 Bits 4-6 */ + boolean EnableTaggedQueuing:1; /* Byte 11 Bit 7 */ } __attribute__ ((packed)) ChannelParameters[6]; /* Bytes 12-17 */ unsigned char SCSIInitiatorID; /* Byte 18 */ unsigned char :8; /* Byte 19 */ enum { - DAC960_StartupMode_ControllerSpinUp = 0x00, - DAC960_StartupMode_PowerOnSpinUp = 0x01 + DAC960_V1_StartupMode_ControllerSpinUp = 0x00, + DAC960_V1_StartupMode_PowerOnSpinUp = 0x01 } __attribute__ ((packed)) StartupMode; /* Byte 20 */ unsigned char SimultaneousDeviceSpinUpCount; /* Byte 21 */ unsigned char SecondsDelayBetweenSpinUps; /* Byte 22 */ @@ -623,44 +761,44 @@ boolean CDROMBootEnabled:1; /* Byte 52 Bit 1 */ unsigned char :3; /* Byte 52 Bits 2-4 */ enum { - DAC960_Geometry_128_32 = 0x00, - DAC960_Geometry_255_63 = 0x01, - DAC960_Geometry_Reserved1 = 0x02, - DAC960_Geometry_Reserved2 = 0x03 + DAC960_V1_Geometry_128_32 = 0x0, + DAC960_V1_Geometry_255_63 = 0x1, + DAC960_V1_Geometry_Reserved1 = 0x2, + DAC960_V1_Geometry_Reserved2 = 0x3 } __attribute__ ((packed)) DriveGeometry:2; /* Byte 52 Bits 5-6 */ unsigned char :1; /* Byte 52 Bit 7 */ unsigned char Reserved2[9]; /* Bytes 53-61 */ unsigned short Checksum; /* Bytes 62-63 */ } -DAC960_Config2_T; +DAC960_V1_Config2_T; /* - Define the DCDB request structure. + Define the DAC960 V1 Firmware DCDB request structure. */ -typedef struct DAC960_DCDB +typedef struct DAC960_V1_DCDB { unsigned char TargetID:4; /* Byte 0 Bits 0-3 */ unsigned char Channel:4; /* Byte 0 Bits 4-7 */ enum { - DAC960_DCDB_NoDataTransfer = 0, - DAC960_DCDB_DataTransferDeviceToSystem = 1, - DAC960_DCDB_DataTransferSystemToDevice = 2, - DAC960_DCDB_IllegalDataTransfer = 3 + DAC960_V1_DCDB_NoDataTransfer = 0, + DAC960_V1_DCDB_DataTransferDeviceToSystem = 1, + DAC960_V1_DCDB_DataTransferSystemToDevice = 2, + DAC960_V1_DCDB_IllegalDataTransfer = 3 } __attribute__ ((packed)) Direction:2; /* Byte 1 Bits 0-1 */ boolean EarlyStatus:1; /* Byte 1 Bit 2 */ unsigned char :1; /* Byte 1 Bit 3 */ enum { - DAC960_DCDB_Timeout_24_hours = 0, - DAC960_DCDB_Timeout_10_seconds = 1, - DAC960_DCDB_Timeout_60_seconds = 2, - DAC960_DCDB_Timeout_10_minutes = 3 + DAC960_V1_DCDB_Timeout_24_hours = 0, + DAC960_V1_DCDB_Timeout_10_seconds = 1, + DAC960_V1_DCDB_Timeout_60_seconds = 2, + DAC960_V1_DCDB_Timeout_10_minutes = 3 } __attribute__ ((packed)) Timeout:2; /* Byte 1 Bits 4-5 */ boolean NoAutomaticRequestSense:1; /* Byte 1 Bit 6 */ boolean DisconnectPermitted:1; /* Byte 1 Bit 7 */ unsigned short TransferLength; /* Bytes 2-3 */ - DAC960_BusAddress_T BusAddress; /* Bytes 4-7 */ + DAC960_BusAddress32_T BusAddress; /* Bytes 4-7 */ unsigned char CDBLength:4; /* Byte 8 Bits 0-3 */ unsigned char TransferLengthHigh4:4; /* Byte 8 Bits 4-7 */ unsigned char SenseLength; /* Byte 9 */ @@ -669,387 +807,1288 @@ unsigned char Status; /* Byte 86 */ unsigned char :8; /* Byte 87 */ } -DAC960_DCDB_T; - - -/* - Define the SCSI INQUIRY Standard Data reply structure. -*/ - -typedef struct DAC960_SCSI_Inquiry -{ - unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */ - unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */ - unsigned char DeviceTypeModifier:7; /* Byte 1 Bits 0-6 */ - boolean RMB:1; /* Byte 1 Bit 7 */ - unsigned char ANSI_ApprovedVersion:3; /* Byte 2 Bits 0-2 */ - unsigned char ECMA_Version:3; /* Byte 2 Bits 3-5 */ - unsigned char ISO_Version:2; /* Byte 2 Bits 6-7 */ - unsigned char ResponseDataFormat:4; /* Byte 3 Bits 0-3 */ - unsigned char :2; /* Byte 3 Bits 4-5 */ - boolean TrmIOP:1; /* Byte 3 Bit 6 */ - boolean AENC:1; /* Byte 3 Bit 7 */ - unsigned char AdditionalLength; /* Byte 4 */ - unsigned char :8; /* Byte 5 */ - unsigned char :8; /* Byte 6 */ - boolean SftRe:1; /* Byte 7 Bit 0 */ - boolean CmdQue:1; /* Byte 7 Bit 1 */ - boolean :1; /* Byte 7 Bit 2 */ - boolean Linked:1; /* Byte 7 Bit 3 */ - boolean Sync:1; /* Byte 7 Bit 4 */ - boolean WBus16:1; /* Byte 7 Bit 5 */ - boolean WBus32:1; /* Byte 7 Bit 6 */ - boolean RelAdr:1; /* Byte 7 Bit 7 */ - unsigned char VendorIdentification[8]; /* Bytes 8-15 */ - unsigned char ProductIdentification[16]; /* Bytes 16-31 */ - unsigned char ProductRevisionLevel[4]; /* Bytes 32-35 */ -} -DAC960_SCSI_Inquiry_T; - - -/* - Define the SCSI INQUIRY Unit Serial Number reply structure. -*/ - -typedef struct DAC960_SCSI_Inquiry_UnitSerialNumber -{ - unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */ - unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */ - unsigned char PageCode; /* Byte 1 */ - unsigned char :8; /* Byte 2 */ - unsigned char PageLength; /* Byte 3 */ - unsigned char ProductSerialNumber[28]; /* Bytes 4 - 31 */ -} -DAC960_SCSI_Inquiry_UnitSerialNumber_T; +DAC960_V1_DCDB_T; /* - Define the Scatter/Gather List Type 1 32 Bit Address 32 Bit Byte Count - structure. + Define the DAC960 V1 Firmware Scatter/Gather List Type 1 32 Bit Address + 32 Bit Byte Count structure. */ -typedef struct DAC960_ScatterGatherSegment +typedef struct DAC960_V1_ScatterGatherSegment { - DAC960_BusAddress_T SegmentDataPointer; /* Bytes 0-3 */ - DAC960_ByteCount_T SegmentByteCount; /* Bytes 4-7 */ + DAC960_BusAddress32_T SegmentDataPointer; /* Bytes 0-3 */ + DAC960_ByteCount32_T SegmentByteCount; /* Bytes 4-7 */ } -DAC960_ScatterGatherSegment_T; +DAC960_V1_ScatterGatherSegment_T; /* - Define the 13 Byte DAC960 Command Mailbox structure. Bytes 13-15 are - not used. The Command Mailbox structure is padded to 16 bytes for + Define the 13 Byte DAC960 V1 Firmware Command Mailbox structure. Bytes 13-15 + are not used. The Command Mailbox structure is padded to 16 bytes for efficient access. */ -typedef union DAC960_CommandMailbox +typedef union DAC960_V1_CommandMailbox { unsigned int Words[4]; /* Words 0-3 */ unsigned char Bytes[16]; /* Bytes 0-15 */ struct { - DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ - DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + DAC960_V1_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_V1_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ unsigned char Dummy[14]; /* Bytes 2-15 */ } __attribute__ ((packed)) Common; struct { - DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ - DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + DAC960_V1_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_V1_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ unsigned char Dummy1[6]; /* Bytes 2-7 */ - DAC960_BusAddress_T BusAddress; /* Bytes 8-11 */ + DAC960_BusAddress32_T BusAddress; /* Bytes 8-11 */ unsigned char Dummy2[4]; /* Bytes 12-15 */ } __attribute__ ((packed)) Type3; struct { - DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ - DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + DAC960_V1_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_V1_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ unsigned char Dummy1[5]; /* Bytes 2-6 */ unsigned char LogicalDriveNumber:6; /* Byte 7 Bits 0-6 */ boolean AutoRestore:1; /* Byte 7 Bit 7 */ unsigned char Dummy2[8]; /* Bytes 8-15 */ } __attribute__ ((packed)) Type3C; struct { - DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ - DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + DAC960_V1_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_V1_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ unsigned char Channel; /* Byte 2 */ unsigned char TargetID; /* Byte 3 */ - DAC960_PhysicalDeviceState_T DeviceState:5; /* Byte 4 Bits 0-4 */ + DAC960_V1_PhysicalDeviceState_T DeviceState:5; /* Byte 4 Bits 0-4 */ unsigned char Modifier:3; /* Byte 4 Bits 5-7 */ unsigned char Dummy1[3]; /* Bytes 5-7 */ - DAC960_BusAddress_T BusAddress; /* Bytes 8-11 */ + DAC960_BusAddress32_T BusAddress; /* Bytes 8-11 */ unsigned char Dummy2[4]; /* Bytes 12-15 */ } __attribute__ ((packed)) Type3D; struct { - DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ - DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ - DAC960_PerformEventLogOpType_T OperationType; /* Byte 2 */ + DAC960_V1_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_V1_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + DAC960_V1_PerformEventLogOpType_T OperationType; /* Byte 2 */ unsigned char OperationQualifier; /* Byte 3 */ unsigned short SequenceNumber; /* Bytes 4-5 */ unsigned char Dummy1[2]; /* Bytes 6-7 */ - DAC960_BusAddress_T BusAddress; /* Bytes 8-11 */ + DAC960_BusAddress32_T BusAddress; /* Bytes 8-11 */ unsigned char Dummy2[4]; /* Bytes 12-15 */ } __attribute__ ((packed)) Type3E; struct { - DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ - DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + DAC960_V1_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_V1_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ unsigned char Dummy1[2]; /* Bytes 2-3 */ unsigned char RebuildRateConstant; /* Byte 4 */ unsigned char Dummy2[3]; /* Bytes 5-7 */ - DAC960_BusAddress_T BusAddress; /* Bytes 8-11 */ + DAC960_BusAddress32_T BusAddress; /* Bytes 8-11 */ unsigned char Dummy3[4]; /* Bytes 12-15 */ } __attribute__ ((packed)) Type3R; struct { - DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ - DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + DAC960_V1_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_V1_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ unsigned short TransferLength; /* Bytes 2-3 */ unsigned int LogicalBlockAddress; /* Bytes 4-7 */ - DAC960_BusAddress_T BusAddress; /* Bytes 8-11 */ + DAC960_BusAddress32_T BusAddress; /* Bytes 8-11 */ unsigned char LogicalDriveNumber; /* Byte 12 */ unsigned char Dummy[3]; /* Bytes 13-15 */ } __attribute__ ((packed)) Type4; struct { - DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ - DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + DAC960_V1_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_V1_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ struct { unsigned short TransferLength:11; /* Bytes 2-3 */ unsigned char LogicalDriveNumber:5; /* Byte 3 Bits 3-7 */ } __attribute__ ((packed)) LD; unsigned int LogicalBlockAddress; /* Bytes 4-7 */ - DAC960_BusAddress_T BusAddress; /* Bytes 8-11 */ + DAC960_BusAddress32_T BusAddress; /* Bytes 8-11 */ unsigned char ScatterGatherCount:6; /* Byte 12 Bits 0-5 */ enum { - DAC960_ScatterGather_32BitAddress_32BitByteCount = 0x0, - DAC960_ScatterGather_32BitAddress_16BitByteCount = 0x1, - DAC960_ScatterGather_32BitByteCount_32BitAddress = 0x2, - DAC960_ScatterGather_16BitByteCount_32BitAddress = 0x3 + DAC960_V1_ScatterGather_32BitAddress_32BitByteCount = 0x0, + DAC960_V1_ScatterGather_32BitAddress_16BitByteCount = 0x1, + DAC960_V1_ScatterGather_32BitByteCount_32BitAddress = 0x2, + DAC960_V1_ScatterGather_16BitByteCount_32BitAddress = 0x3 } __attribute__ ((packed)) ScatterGatherType:2; /* Byte 12 Bits 6-7 */ unsigned char Dummy[3]; /* Bytes 13-15 */ } __attribute__ ((packed)) Type5; struct { - DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ - DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + DAC960_V1_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_V1_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ unsigned char CommandOpcode2; /* Byte 2 */ unsigned char :8; /* Byte 3 */ - DAC960_BusAddress_T CommandMailboxesBusAddress; /* Bytes 4-7 */ - DAC960_BusAddress_T StatusMailboxesBusAddress; /* Bytes 8-11 */ + DAC960_BusAddress32_T CommandMailboxesBusAddress; /* Bytes 4-7 */ + DAC960_BusAddress32_T StatusMailboxesBusAddress; /* Bytes 8-11 */ unsigned char Dummy[4]; /* Bytes 12-15 */ } __attribute__ ((packed)) TypeX; } -DAC960_CommandMailbox_T; +DAC960_V1_CommandMailbox_T; /* - Define the DAC960 Driver IOCTL requests. + Define the DAC960 V2 Firmware Command Opcodes. */ -#define DAC960_IOCTL_GET_CONTROLLER_COUNT 0xDAC001 -#define DAC960_IOCTL_GET_CONTROLLER_INFO 0xDAC002 -#define DAC960_IOCTL_EXECUTE_COMMAND 0xDAC003 +typedef enum +{ + DAC960_V2_MemCopy = 0x01, + DAC960_V2_SCSI_10_Passthru = 0x02, + DAC960_V2_SCSI_255_Passthru = 0x03, + DAC960_V2_SCSI_10 = 0x04, + DAC960_V2_SCSI_256 = 0x05, + DAC960_V2_IOCTL = 0x20 +} +__attribute__ ((packed)) +DAC960_V2_CommandOpcode_T; /* - Define the DAC960_IOCTL_GET_CONTROLLER_INFO reply structure. + Define the DAC960 V2 Firmware IOCTL Opcodes. */ -typedef struct DAC960_ControllerInfo +typedef enum { - unsigned char ControllerNumber; - unsigned char PCI_Bus; - unsigned char PCI_Device; - unsigned char PCI_Function; - unsigned char IRQ_Channel; - unsigned char Channels; - DAC960_PCI_Address_T PCI_Address; - unsigned char ModelName[16]; - unsigned char FirmwareVersion[16]; + DAC960_V2_GetControllerInfo = 0x01, + DAC960_V2_GetLogicalDeviceInfoValid = 0x03, + DAC960_V2_GetPhysicalDeviceInfoValid = 0x05, + DAC960_V2_GetHealthStatus = 0x11, + DAC960_V2_GetEvent = 0x15, + DAC960_V2_SetDeviceState = 0x82, + DAC960_V2_RebuildDeviceStart = 0x88, + DAC960_V2_RebuildDeviceStop = 0x89, + DAC960_V2_ConsistencyCheckStart = 0x8C, + DAC960_V2_ConsistencyCheckStop = 0x8D, + DAC960_V2_SetMemoryMailbox = 0x8E, + DAC960_V2_PauseDevice = 0x92, + DAC960_V2_TranslatePhysicalToLogicalDevice = 0xC5 } -DAC960_ControllerInfo_T; +__attribute__ ((packed)) +DAC960_V2_IOCTL_Opcode_T; /* - Define the User Mode DAC960_IOCTL_EXECUTE_COMMAND request structure. + Define the DAC960 V2 Firmware Command Identifier type. */ -typedef struct DAC960_UserCommand -{ - unsigned char ControllerNumber; - DAC960_CommandMailbox_T CommandMailbox; - int DataTransferLength; - void *DataTransferBuffer; - DAC960_DCDB_T *DCDB; -} -DAC960_UserCommand_T; +typedef unsigned short DAC960_V2_CommandIdentifier_T; /* - Define the Kernel Mode DAC960_IOCTL_EXECUTE_COMMAND request structure. + Define the DAC960 V2 Firmware Command Status Codes. */ -typedef struct DAC960_KernelCommand -{ - unsigned char ControllerNumber; - DAC960_CommandMailbox_T CommandMailbox; - int DataTransferLength; - void *DataTransferBuffer; - DAC960_DCDB_T *DCDB; - DAC960_CommandStatus_T CommandStatus; - void (*CompletionFunction)(struct DAC960_KernelCommand *); - void *CompletionData; -} -DAC960_KernelCommand_T; +#define DAC960_V2_NormalCompletion 0x00 +#define DAC960_V2_AbormalCompletion 0x02 +#define DAC960_V2_DeviceNonresponsive 0x0E + +typedef unsigned char DAC960_V2_CommandStatus_T; /* - Import the Kernel Mode IOCTL interface. + Define the DAC960 V2 Firmware Memory Type structure. */ -extern int DAC960_KernelIOCTL(unsigned int Request, void *Argument); +typedef struct DAC960_V2_MemoryType +{ + enum { + DAC960_V2_MemoryType_Reserved = 0x00, + DAC960_V2_MemoryType_DRAM = 0x01, + DAC960_V2_MemoryType_EDRAM = 0x02, + DAC960_V2_MemoryType_EDO = 0x03, + DAC960_V2_MemoryType_SDRAM = 0x04 + } __attribute__ ((packed)) MemoryType:5; /* Byte 0 Bits 0-4 */ + boolean :1; /* Byte 0 Bit 5 */ + boolean MemoryParity:1; /* Byte 0 Bit 6 */ + boolean MemoryECC:1; /* Byte 0 Bit 7 */ +} +DAC960_V2_MemoryType_T; /* - Virtual_to_Bus maps from Kernel Virtual Addresses to PCI Bus Addresses. + Define the DAC960 V2 Firmware Processor Type structure. */ -static inline DAC960_BusAddress_T Virtual_to_Bus(void *VirtualAddress) +typedef enum { - return (DAC960_BusAddress_T) virt_to_bus(VirtualAddress); + DAC960_V2_ProcessorType_i960CA = 0x01, + DAC960_V2_ProcessorType_i960RD = 0x02, + DAC960_V2_ProcessorType_i960RN = 0x03, + DAC960_V2_ProcessorType_i960RP = 0x04, + DAC960_V2_ProcessorType_NorthBay = 0x05, + DAC960_V2_ProcessorType_StrongArm = 0x06, + DAC960_V2_ProcessorType_i960RM = 0x07 } +__attribute__ ((packed)) +DAC960_V2_ProcessorType_T; /* - Bus_to_Virtual maps from PCI Bus Addresses to Kernel Virtual Addresses. + Define the DAC960 V2 Firmware Get Controller Info reply structure. */ -static inline void *Bus_to_Virtual(DAC960_BusAddress_T BusAddress) +typedef struct DAC960_V2_ControllerInfo { - return (void *) bus_to_virt(BusAddress); + unsigned char :8; /* Byte 0 */ + enum { + DAC960_V2_SCSI_Bus = 0x00, + DAC960_V2_Fibre_Bus = 0x01, + DAC960_V2_PCI_Bus = 0x03 + } __attribute__ ((packed)) BusInterfaceType; /* Byte 1 */ + enum { + DAC960_V2_DAC960E = 0x01, + DAC960_V2_DAC960M = 0x08, + DAC960_V2_DAC960PD = 0x10, + DAC960_V2_DAC960PL = 0x11, + DAC960_V2_DAC960PU = 0x12, + DAC960_V2_DAC960PE = 0x13, + DAC960_V2_DAC960PG = 0x14, + DAC960_V2_DAC960PJ = 0x15, + DAC960_V2_DAC960PTL0 = 0x16, + DAC960_V2_DAC960PR = 0x17, + DAC960_V2_DAC960PRL = 0x18, + DAC960_V2_DAC960PT = 0x19, + DAC960_V2_DAC1164P = 0x1A, + DAC960_V2_DAC960PTL1 = 0x1B, + DAC960_V2_EXR2000P = 0x1C, + DAC960_V2_EXR3000P = 0x1D, + DAC960_V2_AcceleRAID352 = 0x1E, + DAC960_V2_AcceleRAID351 = 0x1F, + DAC960_V2_DAC960S = 0x60, + DAC960_V2_DAC960SU = 0x61, + DAC960_V2_DAC960SX = 0x62, + DAC960_V2_DAC960SF = 0x63, + DAC960_V2_DAC960SS = 0x64, + DAC960_V2_DAC960FL = 0x65, + DAC960_V2_DAC960LL = 0x66, + DAC960_V2_DAC960FF = 0x67, + DAC960_V2_DAC960HP = 0x68, + DAC960_V2_RAIDBRICK = 0x69, + DAC960_V2_METEOR_FL = 0x6A, + DAC960_V2_METEOR_FF = 0x6B + } __attribute__ ((packed)) ControllerType; /* Byte 2 */ + unsigned char :8; /* Byte 3 */ + unsigned short BusInterfaceSpeedMHz; /* Bytes 4-5 */ + unsigned char BusWidthBits; /* Byte 6 */ + unsigned char Reserved1[9]; /* Bytes 7-15 */ + unsigned char BusInterfaceName[16]; /* Bytes 16-31 */ + unsigned char ControllerName[16]; /* Bytes 32-47 */ + unsigned char Reserved2[16]; /* Bytes 48-63 */ + /* Firmware Release Information */ + unsigned char FirmwareMajorVersion; /* Byte 64 */ + unsigned char FirmwareMinorVersion; /* Byte 65 */ + unsigned char FirmwareTurnNumber; /* Byte 66 */ + unsigned char FirmwareBuildNumber; /* Byte 67 */ + unsigned char FirmwareReleaseDay; /* Byte 68 */ + unsigned char FirmwareReleaseMonth; /* Byte 69 */ + unsigned char FirmwareReleaseYearHigh2Digits; /* Byte 70 */ + unsigned char FirmwareReleaseYearLow2Digits; /* Byte 71 */ + /* Hardware Release Information */ + unsigned char HardwareRevision; /* Byte 72 */ + unsigned int :24; /* Bytes 73-75 */ + unsigned char HardwareReleaseDay; /* Byte 76 */ + unsigned char HardwareReleaseMonth; /* Byte 77 */ + unsigned char HardwareReleaseYearHigh2Digits; /* Byte 78 */ + unsigned char HardwareReleaseYearLow2Digits; /* Byte 79 */ + /* Hardware Manufacturing Information */ + unsigned char ManufacturingBatchNumber; /* Byte 80 */ + unsigned char :8; /* Byte 81 */ + unsigned char ManufacturingPlantNumber; /* Byte 82 */ + unsigned char :8; /* Byte 83 */ + unsigned char HardwareManufacturingDay; /* Byte 84 */ + unsigned char HardwareManufacturingMonth; /* Byte 85 */ + unsigned char HardwareManufacturingYearHigh2Digits; /* Byte 86 */ + unsigned char HardwareManufacturingYearLow2Digits; /* Byte 87 */ + unsigned char MaximumNumberOfPDDperXLDD; /* Byte 88 */ + unsigned char MaximumNumberOfILDDperXLDD; /* Byte 89 */ + unsigned short NonvolatileMemorySizeKB; /* Bytes 90-91 */ + unsigned char MaximumNumberOfXLDD; /* Byte 92 */ + unsigned int :24; /* Bytes 93-95 */ + /* Unique Information per Controller */ + unsigned char ControllerSerialNumber[16]; /* Bytes 96-111 */ + unsigned char Reserved3[16]; /* Bytes 112-127 */ + /* Vendor Information */ + unsigned int :24; /* Bytes 128-130 */ + unsigned char OEM_Information; /* Byte 131 */ + unsigned char VendorName[16]; /* Bytes 132-147 */ + /* Other Physical/Controller/Operation Information */ + boolean BBU_Present:1; /* Byte 148 Bit 0 */ + boolean ActiveActiveClusteringMode:1; /* Byte 148 Bit 1 */ + unsigned char :6; /* Byte 148 Bits 2-7 */ + unsigned char :8; /* Byte 149 */ + unsigned short :16; /* Bytes 150-151 */ + /* Physical Device Scan Information */ + boolean PhysicalScanActive:1; /* Byte 152 Bit 0 */ + unsigned char :7; /* Byte 152 Bits 1-7 */ + unsigned char PhysicalDeviceChannelNumber; /* Byte 153 */ + unsigned char PhysicalDeviceTargetID; /* Byte 154 */ + unsigned char PhysicalDeviceLogicalUnit; /* Byte 155 */ + /* Maximum Command Data Transfer Sizes */ + unsigned short MaximumDataTransferSizeInBlocks; /* Bytes 156-157 */ + unsigned short MaximumScatterGatherEntries; /* Bytes 158-159 */ + /* Logical/Physical Device Counts */ + unsigned short LogicalDevicesPresent; /* Bytes 160-161 */ + unsigned short LogicalDevicesCritical; /* Bytes 162-163 */ + unsigned short LogicalDevicesOffline; /* Bytes 164-165 */ + unsigned short PhysicalDevicesPresent; /* Bytes 166-167 */ + unsigned short PhysicalDisksPresent; /* Bytes 168-169 */ + unsigned short PhysicalDisksCritical; /* Bytes 170-171 */ + unsigned short PhysicalDisksOffline; /* Bytes 172-173 */ + unsigned short MaximumParallelCommands; /* Bytes 174-175 */ + /* Channel and Target ID Information */ + unsigned char NumberOfPhysicalChannelsPresent; /* Byte 176 */ + unsigned char NumberOfVirtualChannelsPresent; /* Byte 177 */ + unsigned char NumberOfPhysicalChannelsPossible; /* Byte 178 */ + unsigned char NumberOfVirtualChannelsPossible; /* Byte 179 */ + unsigned char MaximumTargetsPerChannel[16]; /* Bytes 180-195 */ + unsigned char Reserved4[12]; /* Bytes 196-207 */ + /* Memory/Cache Information */ + unsigned short MemorySizeMB; /* Bytes 208-209 */ + unsigned short CacheSizeMB; /* Bytes 210-211 */ + unsigned int ValidCacheSizeInBytes; /* Bytes 212-215 */ + unsigned int DirtyCacheSizeInBytes; /* Bytes 216-219 */ + unsigned short MemorySpeedMHz; /* Bytes 220-221 */ + unsigned char MemoryDataWidthBits; /* Byte 222 */ + DAC960_V2_MemoryType_T MemoryType; /* Byte 223 */ + unsigned char CacheMemoryTypeName[16]; /* Bytes 224-239 */ + /* Execution Memory Information */ + unsigned short ExecutionMemorySizeMB; /* Bytes 240-241 */ + unsigned short ExecutionL2CacheSizeMB; /* Bytes 242-243 */ + unsigned char Reserved5[8]; /* Bytes 244-251 */ + unsigned short ExecutionMemorySpeedMHz; /* Bytes 252-253 */ + unsigned char ExecutionMemoryDataWidthBits; /* Byte 254 */ + DAC960_V2_MemoryType_T ExecutionMemoryType; /* Byte 255 */ + unsigned char ExecutionMemoryTypeName[16]; /* Bytes 256-271 */ + /* First CPU Type Information */ + unsigned short FirstProcessorSpeedMHz; /* Bytes 272-273 */ + DAC960_V2_ProcessorType_T FirstProcessorType; /* Byte 274 */ + unsigned char FirstProcessorCount; /* Byte 275 */ + unsigned char Reserved6[12]; /* Bytes 276-287 */ + unsigned char FirstProcessorName[16]; /* Bytes 288-303 */ + /* Second CPU Type Information */ + unsigned short SecondProcessorSpeedMHz; /* Bytes 304-305 */ + DAC960_V2_ProcessorType_T SecondProcessorType; /* Byte 306 */ + unsigned char SecondProcessorCount; /* Byte 307 */ + unsigned char Reserved7[12]; /* Bytes 308-319 */ + unsigned char SecondProcessorName[16]; /* Bytes 320-335 */ + /* Debugging/Profiling/Command Time Tracing Information */ + unsigned short CurrentProfilingDataPageNumber; /* Bytes 336-337 */ + unsigned short ProgramsAwaitingProfilingData; /* Bytes 338-339 */ + unsigned short CurrentCommandTimeTraceDataPageNumber; /* Bytes 340-341 */ + unsigned short ProgramsAwaitingCommandTimeTraceData; /* Bytes 342-343 */ + unsigned char Reserved8[8]; /* Bytes 344-351 */ + /* Error Counters on Physical Devices */ + unsigned short PhysicalDeviceBusResets; /* Bytes 352-353 */ + unsigned short PhysicalDeviceParityErrors; /* Bytes 355-355 */ + unsigned short PhysicalDeviceSoftErrors; /* Bytes 356-357 */ + unsigned short PhysicalDeviceCommandsFailed; /* Bytes 358-359 */ + unsigned short PhysicalDeviceMiscellaneousErrors; /* Bytes 360-361 */ + unsigned short PhysicalDeviceCommandTimeouts; /* Bytes 362-363 */ + unsigned short PhysicalDeviceSelectionTimeouts; /* Bytes 364-365 */ + unsigned short PhysicalDeviceRetriesDone; /* Bytes 366-367 */ + unsigned short PhysicalDeviceAbortsDone; /* Bytes 368-369 */ + unsigned short PhysicalDeviceHostCommandAbortsDone; /* Bytes 370-371 */ + unsigned short PhysicalDevicePredictedFailuresDetected; /* Bytes 372-373 */ + unsigned short PhysicalDeviceHostCommandsFailed; /* Bytes 374-375 */ + unsigned char Reserved9[8]; /* Bytes 376-383 */ + /* Error Counters on Logical Devices */ + unsigned short LogicalDeviceSoftErrors; /* Bytes 384-385 */ + unsigned short LogicalDeviceCommandsFailed; /* Bytes 386-387 */ + unsigned short LogicalDeviceHostCommandAbortsDone; /* Bytes 388-389 */ + unsigned short :16; /* Bytes 390-391 */ + unsigned short ControllerMemoryErrors; /* Bytes 392-393 */ + unsigned short ControllerHostCommandAbortsDone; /* Bytes 394-395 */ + unsigned int :32; /* Bytes 396-399 */ + /* Long Duration Activity Information */ + unsigned short BackgroundInitializationsActive; /* Bytes 400-401 */ + unsigned short LogicalDeviceInitializationsActive; /* Bytes 402-403 */ + unsigned short PhysicalDeviceInitializationsActive; /* Bytes 404-405 */ + unsigned short ConsistencyChecksActive; /* Bytes 406-407 */ + unsigned short RebuildsActive; /* Bytes 408-409 */ + unsigned short OnlineExpansionsActive; /* Bytes 410-411 */ + unsigned short PatrolActivitiesActive; /* Bytes 412-413 */ + unsigned char LongOperationStatus; /* Byte 414 */ + unsigned char :8; /* Byte 415 */ + /* Flash ROM Information */ + unsigned char FlashType; /* Byte 416 */ + unsigned char :8; /* Byte 417 */ + unsigned short FlashSizeMB; /* Bytes 418-419 */ + unsigned int FlashLimit; /* Bytes 420-423 */ + unsigned int FlashCount; /* Bytes 424-427 */ + unsigned int :32; /* Bytes 428-431 */ + unsigned char FlashTypeName[16]; /* Bytes 432-447 */ + /* Firmware Run Time Information */ + unsigned char RebuildRate; /* Byte 448 */ + unsigned char BackgroundInitializationRate; /* Byte 449 */ + unsigned char ForegroundInitializationRate; /* Byte 450 */ + unsigned char ConsistencyCheckRate; /* Byte 451 */ + unsigned int :32; /* Bytes 452-455 */ + unsigned int MaximumDP; /* Bytes 456-459 */ + unsigned int FreeDP; /* Bytes 460-463 */ + unsigned int MaximumIOP; /* Bytes 464-467 */ + unsigned int FreeIOP; /* Bytes 468-471 */ + unsigned short MaximumCombLengthInBlocks; /* Bytes 472-473 */ + unsigned short NumberOfConfigurationGroups; /* Bytes 474-475 */ + boolean InstallationAbortStatus:1; /* Byte 476 Bit 0 */ + boolean MaintenanceModeStatus:1; /* Byte 476 Bit 1 */ + unsigned int :6; /* Byte 476 Bits 2-7 */ + unsigned int :24; /* Bytes 477-479 */ + unsigned char Reserved10[32]; /* Bytes 480-511 */ + unsigned char Reserved11[512]; /* Bytes 512-1023 */ } +DAC960_V2_ControllerInfo_T; /* - DAC960_DriverVersion protects the private portion of this file. + Define the DAC960 V2 Firmware Logical Device State type. */ -#ifdef DAC960_DriverVersion +typedef enum +{ + DAC960_V2_LogicalDevice_Online = 0x01, + DAC960_V2_LogicalDevice_Offline = 0x08, + DAC960_V2_LogicalDevice_Critical = 0x09 +} +__attribute__ ((packed)) +DAC960_V2_LogicalDeviceState_T; /* - Define the maximum Driver Queue Depth and Controller Queue Depth supported - by any DAC960 model. + Define the DAC960 V2 Firmware Get Logical Device Info reply structure. */ -#define DAC960_MaxDriverQueueDepth 127 -#define DAC960_MaxControllerQueueDepth 128 +typedef struct DAC960_V2_LogicalDeviceInfo +{ + unsigned char :8; /* Byte 0 */ + unsigned char Channel; /* Byte 1 */ + unsigned char TargetID; /* Byte 2 */ + unsigned char LogicalUnit; /* Byte 3 */ + DAC960_V2_LogicalDeviceState_T LogicalDeviceState; /* Byte 4 */ + unsigned char RAIDLevel; /* Byte 5 */ + unsigned char StripeSize; /* Byte 6 */ + unsigned char CacheLineSize; /* Byte 7 */ + struct { + enum { + DAC960_V2_ReadCacheDisabled = 0x0, + DAC960_V2_ReadCacheEnabled = 0x1, + DAC960_V2_ReadAheadEnabled = 0x2, + DAC960_V2_IntelligentReadAheadEnabled = 0x3 + } __attribute__ ((packed)) ReadCache:3; /* Byte 8 Bits 0-2 */ + enum { + DAC960_V2_WriteCacheDisabled = 0x0, + DAC960_V2_LogicalDeviceReadOnly = 0x1, + DAC960_V2_WriteCacheEnabled = 0x2, + DAC960_V2_IntelligentWriteCacheEnabled = 0x3 + } __attribute__ ((packed)) WriteCache:3; /* Byte 8 Bits 3-5 */ + boolean :1; /* Byte 8 Bit 6 */ + boolean LogicalDeviceInitialized:1; /* Byte 8 Bit 7 */ + } LogicalDeviceControl; /* Byte 8 */ + /* Logical Device Operations Status */ + boolean ConsistencyCheckInProgress:1; /* Byte 9 Bit 0 */ + boolean RebuildInProgress:1; /* Byte 9 Bit 1 */ + boolean BackgroundInitializationInProgress:1; /* Byte 9 Bit 2 */ + boolean ForegroundInitializationInProgress:1; /* Byte 9 Bit 3 */ + boolean DataMigrationInProgress:1; /* Byte 9 Bit 4 */ + boolean PatrolOperationInProgress:1; /* Byte 9 Bit 5 */ + unsigned char :2; /* Byte 9 Bits 6-7 */ + unsigned char RAID5WriteUpdate; /* Byte 10 */ + unsigned char RAID5Algorithm; /* Byte 11 */ + unsigned short LogicalDeviceNumber; /* Bytes 12-13 */ + /* BIOS Info */ + boolean BIOSDisabled:1; /* Byte 14 Bit 0 */ + boolean CDROMBootEnabled:1; /* Byte 14 Bit 1 */ + boolean DriveCoercionEnabled:1; /* Byte 14 Bit 2 */ + boolean WriteSameDisabled:1; /* Byte 14 Bit 3 */ + boolean HBA_ModeEnabled:1; /* Byte 14 Bit 4 */ + enum { + DAC960_V2_Geometry_128_32 = 0x0, + DAC960_V2_Geometry_255_63 = 0x1, + DAC960_V2_Geometry_Reserved1 = 0x2, + DAC960_V2_Geometry_Reserved2 = 0x3 + } __attribute__ ((packed)) DriveGeometry:2; /* Byte 14 Bits 5-6 */ + unsigned char :1; /* Byte 14 Bit 7 */ + unsigned char :8; /* Byte 15 */ + /* Error Counters */ + unsigned short SoftErrors; /* Bytes 16-17 */ + unsigned short CommandsFailed; /* Bytes 18-19 */ + unsigned short HostCommandAbortsDone; /* Bytes 20-21 */ + unsigned short DeferredWriteErrors; /* Bytes 22-23 */ + unsigned int :32; /* Bytes 24-27 */ + unsigned int :32; /* Bytes 28-31 */ + /* Device Size Information */ + unsigned short :16; /* Bytes 32-33 */ + unsigned short DeviceBlockSizeInBytes; /* Bytes 34-35 */ + unsigned int OriginalDeviceSizeIn512ByteBlocksOrMB; /* Bytes 36-39 */ + unsigned int ConfigurableDeviceSizeIn512ByteBlocksOrMB; /* Bytes 40-43 */ + unsigned int :32; /* Bytes 44-47 */ + unsigned char LogicalDeviceName[32]; /* Bytes 48-79 */ + unsigned char SCSI_InquiryData[36]; /* Bytes 80-115 */ + unsigned char Reserved1[12]; /* Bytes 116-127 */ + DAC960_ByteCount64_T LastReadBlockNumber; /* Bytes 128-135 */ + DAC960_ByteCount64_T LastWrittenBlockNumber; /* Bytes 136-143 */ + DAC960_ByteCount64_T ConsistencyCheckBlockNumber; /* Bytes 144-151 */ + DAC960_ByteCount64_T RebuildBlockNumber; /* Bytes 152-159 */ + DAC960_ByteCount64_T BackgroundInitializationBlockNumber; /* Bytes 160-167 */ + DAC960_ByteCount64_T ForegroundInitializationBlockNumber; /* Bytes 168-175 */ + DAC960_ByteCount64_T DataMigrationBlockNumber; /* Bytes 176-183 */ + DAC960_ByteCount64_T PatrolOperationBlockNumber; /* Bytes 184-191 */ + unsigned char Reserved2[64]; /* Bytes 192-255 */ +} +DAC960_V2_LogicalDeviceInfo_T; /* - Define the maximum number of Scatter/Gather Segments supported by any - DAC960 model. + Define the DAC960 V2 Firmware Physical Device State type. */ -#define DAC960_MaxScatterGatherSegments 33 +typedef enum +{ + DAC960_V2_Device_Unconfigured = 0x00, + DAC960_V2_Device_Online = 0x01, + DAC960_V2_Device_WriteOnly = 0x03, + DAC960_V2_Device_Dead = 0x08, + DAC960_V2_Device_Standby = 0x21, + DAC960_V2_Device_InvalidState = 0xFF +} +__attribute__ ((packed)) +DAC960_V2_PhysicalDeviceState_T; /* - Define the number of Command Mailboxes and Status Mailboxes used by the - Memory Mailbox Interface. + Define the DAC960 V2 Firmware Get Physical Device Info reply structure. */ -#define DAC960_CommandMailboxCount 256 -#define DAC960_StatusMailboxCount 1024 +typedef struct DAC960_V2_PhysicalDeviceInfo +{ + unsigned char :8; /* Byte 0 */ + unsigned char Channel; /* Byte 1 */ + unsigned char TargetID; /* Byte 2 */ + unsigned char LogicalUnit; /* Byte 3 */ + /* Configuration Status Bits */ + boolean PhysicalDeviceFaultTolerant:1; /* Byte 4 Bit 0 */ + boolean :1; /* Byte 4 Bit 1 */ + boolean PhysicalDeviceLocalToController:1; /* Byte 4 Bit 2 */ + unsigned char :5; /* Byte 4 Bits 3-7 */ + /* Multiple Host/Controller Status Bits */ + boolean RemoteHostSystemDead:1; /* Byte 5 Bit 0 */ + boolean RemoteControllerDead:1; /* Byte 5 Bit 1 */ + unsigned char :6; /* Byte 5 Bits 2-7 */ + DAC960_V2_PhysicalDeviceState_T PhysicalDeviceState; /* Byte 6 */ + unsigned char NegotiatedDataWidthBits; /* Byte 7 */ + unsigned short NegotiatedSynchronousMegaTransfers; /* Bytes 8-9 */ + /* Multiported Physical Device Information */ + unsigned char NumberOfPortConnections; /* Byte 10 */ + unsigned char DriveAccessibilityBitmap; /* Byte 11 */ + unsigned int :32; /* Bytes 12-15 */ + unsigned char NetworkAddress[16]; /* Bytes 16-31 */ + unsigned short MaximumTags; /* Bytes 32-33 */ + /* Physical Device Operations Status */ + boolean ConsistencyCheckInProgress:1; /* Byte 34 Bit 0 */ + boolean RebuildInProgress:1; /* Byte 34 Bit 1 */ + boolean MakingDataConsistentInProgress:1; /* Byte 34 Bit 2 */ + boolean PhysicalDeviceInitializationInProgress:1; /* Byte 34 Bit 3 */ + boolean DataMigrationInProgress:1; /* Byte 34 Bit 4 */ + boolean PatrolOperationInProgress:1; /* Byte 34 Bit 5 */ + unsigned char :2; /* Byte 34 Bits 6-7 */ + unsigned char LongOperationStatus; /* Byte 35 */ + unsigned char ParityErrors; /* Byte 36 */ + unsigned char SoftErrors; /* Byte 37 */ + unsigned char HardErrors; /* Byte 38 */ + unsigned char MiscellaneousErrors; /* Byte 39 */ + unsigned char CommandTimeouts; /* Byte 40 */ + unsigned char Retries; /* Byte 41 */ + unsigned char Aborts; /* Byte 42 */ + unsigned char PredictedFailuresDetected; /* Byte 43 */ + unsigned int :32; /* Bytes 44-47 */ + unsigned short :16; /* Bytes 48-49 */ + unsigned short DeviceBlockSizeInBytes; /* Bytes 50-51 */ + unsigned int OriginalDeviceSizeIn512ByteBlocksOrMB; /* Bytes 52-55 */ + unsigned int ConfigurableDeviceSizeIn512ByteBlocksOrMB; /* Bytes 56-59 */ + unsigned int :32; /* Bytes 60-63 */ + unsigned char PhysicalDeviceName[16]; /* Bytes 64-79 */ + unsigned char Reserved1[16]; /* Bytes 80-95 */ + unsigned char Reserved2[32]; /* Bytes 96-127 */ + unsigned char SCSI_InquiryData[36]; /* Bytes 128-163 */ + unsigned char Reserved3[12]; /* Bytes 164-175 */ + unsigned char Reserved4[16]; /* Bytes 176-191 */ + DAC960_ByteCount64_T LastReadBlockNumber; /* Bytes 192-199 */ + DAC960_ByteCount64_T LastWrittenBlockNumber; /* Bytes 200-207 */ + DAC960_ByteCount64_T ConsistencyCheckBlockNumber; /* Bytes 208-215 */ + DAC960_ByteCount64_T RebuildBlockNumber; /* Bytes 216-223 */ + DAC960_ByteCount64_T MakingDataConsistentBlockNumber; /* Bytes 224-231 */ + DAC960_ByteCount64_T DeviceInitializationBlockNumber; /* Bytes 232-239 */ + DAC960_ByteCount64_T DataMigrationBlockNumber; /* Bytes 240-247 */ + DAC960_ByteCount64_T PatrolOperationBlockNumber; /* Bytes 248-255 */ + unsigned char Reserved5[256]; /* Bytes 256-511 */ +} +DAC960_V2_PhysicalDeviceInfo_T; + + +/* + Define the DAC960 V2 Firmware Health Status Buffer structure. +*/ + +typedef struct DAC960_V2_HealthStatusBuffer +{ + unsigned int MicrosecondsFromControllerStartTime; /* Bytes 0-3 */ + unsigned int MillisecondsFromControllerStartTime; /* Bytes 4-7 */ + unsigned int SecondsFrom1January1970; /* Bytes 8-11 */ + unsigned int :32; /* Bytes 12-15 */ + unsigned int StatusChangeCounter; /* Bytes 16-19 */ + unsigned int :32; /* Bytes 20-23 */ + unsigned int DebugOutputMessageBufferIndex; /* Bytes 24-27 */ + unsigned int CodedMessageBufferIndex; /* Bytes 28-31 */ + unsigned int CurrentTimeTracePageNumber; /* Bytes 32-35 */ + unsigned int CurrentProfilerPageNumber; /* Bytes 36-39 */ + unsigned int NextEventSequenceNumber; /* Bytes 40-43 */ + unsigned int :32; /* Bytes 44-47 */ + unsigned char Reserved1[16]; /* Bytes 48-63 */ + unsigned char Reserved2[64]; /* Bytes 64-127 */ +} +DAC960_V2_HealthStatusBuffer_T; /* - Define the DAC960 Controller Monitoring Timer Interval. + Define the DAC960 V2 Firmware Get Event reply structure. */ -#define DAC960_MonitoringTimerInterval (10 * HZ) +typedef struct DAC960_V2_Event +{ + unsigned int EventSequenceNumber; /* Bytes 0-3 */ + unsigned int EventTime; /* Bytes 4-7 */ + unsigned int EventCode; /* Bytes 8-11 */ + unsigned char :8; /* Byte 12 */ + unsigned char Channel; /* Byte 13 */ + unsigned char TargetID; /* Byte 14 */ + unsigned char LogicalUnit; /* Byte 15 */ + unsigned int :32; /* Bytes 16-19 */ + unsigned int EventSpecificParameter; /* Bytes 20-23 */ + unsigned char RequestSenseData[40]; /* Bytes 24-63 */ +} +DAC960_V2_Event_T; /* - Define the DAC960 Controller Secondary Monitoring Interval. + Define the DAC960 V2 Firmware Command Control Bits structure. */ -#define DAC960_SecondaryMonitoringInterval (60 * HZ) +typedef struct DAC960_V2_CommandControlBits +{ + boolean ForceUnitAccess:1; /* Byte 0 Bit 0 */ + boolean DisablePageOut:1; /* Byte 0 Bit 1 */ + boolean :1; /* Byte 0 Bit 2 */ + boolean AdditionalScatterGatherListMemory:1; /* Byte 0 Bit 3 */ + boolean DataTransferControllerToHost:1; /* Byte 0 Bit 4 */ + boolean :1; /* Byte 0 Bit 5 */ + boolean NoAutoRequestSense:1; /* Byte 0 Bit 6 */ + boolean DisconnectProhibited:1; /* Byte 0 Bit 7 */ +} +DAC960_V2_CommandControlBits_T; /* - Define the DAC960 Controller Progress Reporting Interval. + Define the DAC960 V2 Firmware Command Timeout structure. */ -#define DAC960_ProgressReportingInterval (60 * HZ) +typedef struct DAC960_V2_CommandTimeout +{ + unsigned char TimeoutValue:6; /* Byte 0 Bits 0-5 */ + enum { + DAC960_V2_TimeoutScale_Seconds = 0, + DAC960_V2_TimeoutScale_Minutes = 1, + DAC960_V2_TimeoutScale_Hours = 2, + DAC960_V2_TimeoutScale_Reserved = 3 + } __attribute__ ((packed)) TimeoutScale:2; /* Byte 0 Bits 6-7 */ +} +DAC960_V2_CommandTimeout_T; /* - Define the maximum number of Partitions allowed for each Logical Drive. + Define the DAC960 V2 Firmware Physical Device structure. */ -#define DAC960_MaxPartitions 8 -#define DAC960_MaxPartitionsBits 3 +typedef struct DAC960_V2_PhysicalDevice +{ + unsigned char LogicalUnit; /* Byte 0 */ + unsigned char TargetID; /* Byte 1 */ + unsigned char Channel:3; /* Byte 2 Bits 0-2 */ + unsigned char Controller:5; /* Byte 2 Bits 3-7 */ +} +__attribute__ ((packed)) +DAC960_V2_PhysicalDevice_T; /* - Define macros to extract the Controller Number, Logical Drive Number, and - Partition Number from a Kernel Device, and to construct a Major Number, Minor - Number, and Kernel Device from the Controller Number, Logical Drive Number, - and Partition Number. There is one Major Number assigned to each Controller. - The associated Minor Number is divided into the Logical Drive Number and - Partition Number. + Define the DAC960 V2 Firmware Logical Device structure. */ -#define DAC960_ControllerNumber(Device) \ - (MAJOR(Device) - DAC960_MAJOR) +typedef struct DAC960_V2_LogicalDevice +{ + unsigned short LogicalDeviceNumber; /* Bytes 0-1 */ + unsigned char :3; /* Byte 2 Bits 0-2 */ + unsigned char Controller:5; /* Byte 2 Bits 3-7 */ +} +__attribute__ ((packed)) +DAC960_V2_LogicalDevice_T; -#define DAC960_LogicalDriveNumber(Device) \ - (MINOR(Device) >> DAC960_MaxPartitionsBits) -#define DAC960_PartitionNumber(Device) \ - (MINOR(Device) & (DAC960_MaxPartitions - 1)) +/* + Define the DAC960 V2 Firmware Operation Device type. +*/ -#define DAC960_MajorNumber(ControllerNumber) \ - (DAC960_MAJOR + (ControllerNumber)) +typedef enum +{ + DAC960_V2_Physical_Device = 0x00, + DAC960_V2_RAID_Device = 0x01, + DAC960_V2_Physical_Channel = 0x02, + DAC960_V2_RAID_Channel = 0x03, + DAC960_V2_Physical_Controller = 0x04, + DAC960_V2_RAID_Controller = 0x05, + DAC960_V2_Configuration_Group = 0x10 +} +__attribute__ ((packed)) +DAC960_V2_OperationDevice_T; -#define DAC960_MinorNumber(LogicalDriveNumber, PartitionNumber) \ - (((LogicalDriveNumber) << DAC960_MaxPartitionsBits) | (PartitionNumber)) -#define DAC960_MinorCount (DAC960_MaxLogicalDrives \ - * DAC960_MaxPartitions) +/* + Define the DAC960 V2 Firmware Translate Physical To Logical Device structure. +*/ + +typedef struct DAC960_V2_PhysicalToLogicalDevice +{ + unsigned short LogicalDeviceNumber; /* Bytes 0-1 */ + unsigned short :16; /* Bytes 2-3 */ + unsigned char PreviousBootController; /* Byte 4 */ + unsigned char PreviousBootChannel; /* Byte 5 */ + unsigned char PreviousBootTargetID; /* Byte 6 */ + unsigned char PreviousBootLogicalUnit; /* Byte 7 */ +} +DAC960_V2_PhysicalToLogicalDevice_T; -#define DAC960_KernelDevice(ControllerNumber, \ - LogicalDriveNumber, \ - PartitionNumber) \ - MKDEV(DAC960_MajorNumber(ControllerNumber), \ - DAC960_MinorNumber(LogicalDriveNumber, PartitionNumber)) /* - Define the DAC960 Controller fixed Block Size and Block Size Bits. + Define the DAC960 V2 Firmware Scatter/Gather List Entry structure. */ -#define DAC960_BlockSize 512 +typedef struct DAC960_V2_ScatterGatherSegment +{ + DAC960_BusAddress64_T SegmentDataPointer; /* Bytes 0-7 */ + DAC960_ByteCount64_T SegmentByteCount; /* Bytes 8-15 */ +} +DAC960_V2_ScatterGatherSegment_T; + + +/* + Define the DAC960 V2 Firmware Data Transfer Memory Address structure. +*/ + +typedef union DAC960_V2_DataTransferMemoryAddress +{ + DAC960_V2_ScatterGatherSegment_T ScatterGatherSegments[2]; /* Bytes 0-31 */ + struct { + unsigned short ScatterGatherList0Length; /* Bytes 0-1 */ + unsigned short ScatterGatherList1Length; /* Bytes 2-3 */ + unsigned short ScatterGatherList2Length; /* Bytes 4-5 */ + unsigned short :16; /* Bytes 6-7 */ + DAC960_BusAddress64_T ScatterGatherList0Address; /* Bytes 8-15 */ + DAC960_BusAddress64_T ScatterGatherList1Address; /* Bytes 16-23 */ + DAC960_BusAddress64_T ScatterGatherList2Address; /* Bytes 24-31 */ + } ExtendedScatterGather; +} +DAC960_V2_DataTransferMemoryAddress_T; + + +/* + Define the 64 Byte DAC960 V2 Firmware Command Mailbox structure. +*/ + +typedef union DAC960_V2_CommandMailbox +{ + unsigned int Words[16]; /* Words 0-15 */ + struct { + DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */ + DAC960_V2_CommandOpcode_T CommandOpcode; /* Byte 2 */ + DAC960_V2_CommandControlBits_T CommandControlBits; /* Byte 3 */ + DAC960_ByteCount32_T DataTransferSize:24; /* Bytes 4-6 */ + unsigned char DataTransferPageNumber; /* Byte 7 */ + DAC960_BusAddress64_T RequestSenseBusAddress; /* Bytes 8-15 */ + unsigned int :24; /* Bytes 16-18 */ + DAC960_V2_CommandTimeout_T CommandTimeout; /* Byte 19 */ + unsigned char RequestSenseSize; /* Byte 20 */ + unsigned char IOCTL_Opcode; /* Byte 21 */ + unsigned char Reserved[10]; /* Bytes 22-31 */ + DAC960_V2_DataTransferMemoryAddress_T + DataTransferMemoryAddress; /* Bytes 32-63 */ + } Common; + struct { + DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */ + DAC960_V2_CommandOpcode_T CommandOpcode; /* Byte 2 */ + DAC960_V2_CommandControlBits_T CommandControlBits; /* Byte 3 */ + DAC960_ByteCount32_T DataTransferSize:24; /* Bytes 4-6 */ + unsigned char DataTransferPageNumber; /* Byte 7 */ + DAC960_BusAddress64_T RequestSenseBusAddress; /* Bytes 8-15 */ + DAC960_V2_PhysicalDevice_T PhysicalDevice; /* Bytes 16-18 */ + DAC960_V2_CommandTimeout_T CommandTimeout; /* Byte 19 */ + unsigned char RequestSenseSize; /* Byte 20 */ + unsigned char CDBLength; /* Byte 21 */ + unsigned char SCSI_CDB[10]; /* Bytes 22-31 */ + DAC960_V2_DataTransferMemoryAddress_T + DataTransferMemoryAddress; /* Bytes 32-63 */ + } SCSI_10; + struct { + DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */ + DAC960_V2_CommandOpcode_T CommandOpcode; /* Byte 2 */ + DAC960_V2_CommandControlBits_T CommandControlBits; /* Byte 3 */ + DAC960_ByteCount32_T DataTransferSize:24; /* Bytes 4-6 */ + unsigned char DataTransferPageNumber; /* Byte 7 */ + DAC960_BusAddress64_T RequestSenseBusAddress; /* Bytes 8-15 */ + DAC960_V2_PhysicalDevice_T PhysicalDevice; /* Bytes 16-18 */ + DAC960_V2_CommandTimeout_T CommandTimeout; /* Byte 19 */ + unsigned char RequestSenseSize; /* Byte 20 */ + unsigned char CDBLength; /* Byte 21 */ + unsigned short :16; /* Bytes 22-23 */ + DAC960_BusAddress64_T SCSI_CDB_BusAddress; /* Bytes 24-31 */ + DAC960_V2_DataTransferMemoryAddress_T + DataTransferMemoryAddress; /* Bytes 32-63 */ + } SCSI_255; + struct { + DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */ + DAC960_V2_CommandOpcode_T CommandOpcode; /* Byte 2 */ + DAC960_V2_CommandControlBits_T CommandControlBits; /* Byte 3 */ + DAC960_ByteCount32_T DataTransferSize:24; /* Bytes 4-6 */ + unsigned char DataTransferPageNumber; /* Byte 7 */ + DAC960_BusAddress64_T RequestSenseBusAddress; /* Bytes 8-15 */ + unsigned short :16; /* Bytes 16-17 */ + unsigned char ControllerNumber; /* Byte 18 */ + DAC960_V2_CommandTimeout_T CommandTimeout; /* Byte 19 */ + unsigned char RequestSenseSize; /* Byte 20 */ + unsigned char IOCTL_Opcode; /* Byte 21 */ + unsigned char Reserved[10]; /* Bytes 22-31 */ + DAC960_V2_DataTransferMemoryAddress_T + DataTransferMemoryAddress; /* Bytes 32-63 */ + } ControllerInfo; + struct { + DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */ + DAC960_V2_CommandOpcode_T CommandOpcode; /* Byte 2 */ + DAC960_V2_CommandControlBits_T CommandControlBits; /* Byte 3 */ + DAC960_ByteCount32_T DataTransferSize:24; /* Bytes 4-6 */ + unsigned char DataTransferPageNumber; /* Byte 7 */ + DAC960_BusAddress64_T RequestSenseBusAddress; /* Bytes 8-15 */ + DAC960_V2_LogicalDevice_T LogicalDevice; /* Bytes 16-18 */ + DAC960_V2_CommandTimeout_T CommandTimeout; /* Byte 19 */ + unsigned char RequestSenseSize; /* Byte 20 */ + unsigned char IOCTL_Opcode; /* Byte 21 */ + unsigned char Reserved[10]; /* Bytes 22-31 */ + DAC960_V2_DataTransferMemoryAddress_T + DataTransferMemoryAddress; /* Bytes 32-63 */ + } LogicalDeviceInfo; + struct { + DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */ + DAC960_V2_CommandOpcode_T CommandOpcode; /* Byte 2 */ + DAC960_V2_CommandControlBits_T CommandControlBits; /* Byte 3 */ + DAC960_ByteCount32_T DataTransferSize:24; /* Bytes 4-6 */ + unsigned char DataTransferPageNumber; /* Byte 7 */ + DAC960_BusAddress64_T RequestSenseBusAddress; /* Bytes 8-15 */ + DAC960_V2_PhysicalDevice_T PhysicalDevice; /* Bytes 16-18 */ + DAC960_V2_CommandTimeout_T CommandTimeout; /* Byte 19 */ + unsigned char RequestSenseSize; /* Byte 20 */ + unsigned char IOCTL_Opcode; /* Byte 21 */ + unsigned char Reserved[10]; /* Bytes 22-31 */ + DAC960_V2_DataTransferMemoryAddress_T + DataTransferMemoryAddress; /* Bytes 32-63 */ + } PhysicalDeviceInfo; + struct { + DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */ + DAC960_V2_CommandOpcode_T CommandOpcode; /* Byte 2 */ + DAC960_V2_CommandControlBits_T CommandControlBits; /* Byte 3 */ + DAC960_ByteCount32_T DataTransferSize:24; /* Bytes 4-6 */ + unsigned char DataTransferPageNumber; /* Byte 7 */ + DAC960_BusAddress64_T RequestSenseBusAddress; /* Bytes 8-15 */ + unsigned short EventSequenceNumberHigh16; /* Bytes 16-17 */ + unsigned char ControllerNumber; /* Byte 18 */ + DAC960_V2_CommandTimeout_T CommandTimeout; /* Byte 19 */ + unsigned char RequestSenseSize; /* Byte 20 */ + unsigned char IOCTL_Opcode; /* Byte 21 */ + unsigned short EventSequenceNumberLow16; /* Bytes 22-23 */ + unsigned char Reserved[8]; /* Bytes 24-31 */ + DAC960_V2_DataTransferMemoryAddress_T + DataTransferMemoryAddress; /* Bytes 32-63 */ + } GetEvent; + struct { + DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */ + DAC960_V2_CommandOpcode_T CommandOpcode; /* Byte 2 */ + DAC960_V2_CommandControlBits_T CommandControlBits; /* Byte 3 */ + DAC960_ByteCount32_T DataTransferSize:24; /* Bytes 4-6 */ + unsigned char DataTransferPageNumber; /* Byte 7 */ + DAC960_BusAddress64_T RequestSenseBusAddress; /* Bytes 8-15 */ + DAC960_V2_LogicalDevice_T LogicalDevice; /* Bytes 16-18 */ + DAC960_V2_CommandTimeout_T CommandTimeout; /* Byte 19 */ + unsigned char RequestSenseSize; /* Byte 20 */ + unsigned char IOCTL_Opcode; /* Byte 21 */ + union { + DAC960_V2_LogicalDeviceState_T LogicalDeviceState; + DAC960_V2_PhysicalDeviceState_T PhysicalDeviceState; + } DeviceState; /* Byte 22 */ + unsigned char Reserved[9]; /* Bytes 23-31 */ + DAC960_V2_DataTransferMemoryAddress_T + DataTransferMemoryAddress; /* Bytes 32-63 */ + } SetDeviceState; + struct { + DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */ + DAC960_V2_CommandOpcode_T CommandOpcode; /* Byte 2 */ + DAC960_V2_CommandControlBits_T CommandControlBits; /* Byte 3 */ + DAC960_ByteCount32_T DataTransferSize:24; /* Bytes 4-6 */ + unsigned char DataTransferPageNumber; /* Byte 7 */ + DAC960_BusAddress64_T RequestSenseBusAddress; /* Bytes 8-15 */ + DAC960_V2_LogicalDevice_T LogicalDevice; /* Bytes 16-18 */ + DAC960_V2_CommandTimeout_T CommandTimeout; /* Byte 19 */ + unsigned char RequestSenseSize; /* Byte 20 */ + unsigned char IOCTL_Opcode; /* Byte 21 */ + boolean RestoreConsistency:1; /* Byte 22 Bit 0 */ + boolean InitializedAreaOnly:1; /* Byte 22 Bit 1 */ + unsigned char :6; /* Byte 22 Bits 2-7 */ + unsigned char Reserved[9]; /* Bytes 23-31 */ + DAC960_V2_DataTransferMemoryAddress_T + DataTransferMemoryAddress; /* Bytes 32-63 */ + } ConsistencyCheck; + struct { + DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */ + DAC960_V2_CommandOpcode_T CommandOpcode; /* Byte 2 */ + DAC960_V2_CommandControlBits_T CommandControlBits; /* Byte 3 */ + unsigned char FirstCommandMailboxSizeKB; /* Byte 4 */ + unsigned char FirstStatusMailboxSizeKB; /* Byte 5 */ + unsigned char SecondCommandMailboxSizeKB; /* Byte 6 */ + unsigned char SecondStatusMailboxSizeKB; /* Byte 7 */ + DAC960_BusAddress64_T RequestSenseBusAddress; /* Bytes 8-15 */ + unsigned int :24; /* Bytes 16-18 */ + DAC960_V2_CommandTimeout_T CommandTimeout; /* Byte 19 */ + unsigned char RequestSenseSize; /* Byte 20 */ + unsigned char IOCTL_Opcode; /* Byte 21 */ + unsigned char HealthStatusBufferSizeKB; /* Byte 22 */ + unsigned char :8; /* Byte 23 */ + DAC960_BusAddress64_T HealthStatusBufferBusAddress; /* Bytes 24-31 */ + DAC960_BusAddress64_T FirstCommandMailboxBusAddress; /* Bytes 32-39 */ + DAC960_BusAddress64_T FirstStatusMailboxBusAddress; /* Bytes 40-47 */ + DAC960_BusAddress64_T SecondCommandMailboxBusAddress; /* Bytes 48-55 */ + DAC960_BusAddress64_T SecondStatusMailboxBusAddress; /* Bytes 56-63 */ + } SetMemoryMailbox; + struct { + DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */ + DAC960_V2_CommandOpcode_T CommandOpcode; /* Byte 2 */ + DAC960_V2_CommandControlBits_T CommandControlBits; /* Byte 3 */ + DAC960_ByteCount32_T DataTransferSize:24; /* Bytes 4-6 */ + unsigned char DataTransferPageNumber; /* Byte 7 */ + DAC960_BusAddress64_T RequestSenseBusAddress; /* Bytes 8-15 */ + DAC960_V2_PhysicalDevice_T PhysicalDevice; /* Bytes 16-18 */ + DAC960_V2_CommandTimeout_T CommandTimeout; /* Byte 19 */ + unsigned char RequestSenseSize; /* Byte 20 */ + unsigned char IOCTL_Opcode; /* Byte 21 */ + DAC960_V2_OperationDevice_T OperationDevice; /* Byte 22 */ + unsigned char Reserved[9]; /* Bytes 23-31 */ + DAC960_V2_DataTransferMemoryAddress_T + DataTransferMemoryAddress; /* Bytes 32-63 */ + } DeviceOperation; +} +__attribute__ ((packed)) +DAC960_V2_CommandMailbox_T; + + +/* + Define the DAC960 Driver IOCTL requests. +*/ + +#define DAC960_IOCTL_GET_CONTROLLER_COUNT 0xDAC001 +#define DAC960_IOCTL_GET_CONTROLLER_INFO 0xDAC002 +#define DAC960_IOCTL_V1_EXECUTE_COMMAND 0xDAC003 +#define DAC960_IOCTL_V2_EXECUTE_COMMAND 0xDAC004 +#define DAC960_IOCTL_V2_GET_HEALTH_STATUS 0xDAC005 + + +/* + Define the DAC960_IOCTL_GET_CONTROLLER_INFO reply structure. +*/ + +typedef struct DAC960_ControllerInfo +{ + unsigned char ControllerNumber; + unsigned char FirmwareType; + unsigned char Channels; + unsigned char Targets; + unsigned char PCI_Bus; + unsigned char PCI_Device; + unsigned char PCI_Function; + unsigned char IRQ_Channel; + DAC960_PCI_Address_T PCI_Address; + unsigned char ModelName[20]; + unsigned char FirmwareVersion[12]; +} +DAC960_ControllerInfo_T; + + +/* + Define the User Mode DAC960_IOCTL_V1_EXECUTE_COMMAND request structure. +*/ + +typedef struct DAC960_V1_UserCommand +{ + unsigned char ControllerNumber; + DAC960_V1_CommandMailbox_T CommandMailbox; + int DataTransferLength; + void *DataTransferBuffer; + DAC960_V1_DCDB_T *DCDB; +} +DAC960_V1_UserCommand_T; + + +/* + Define the Kernel Mode DAC960_IOCTL_V1_EXECUTE_COMMAND request structure. +*/ + +typedef struct DAC960_V1_KernelCommand +{ + unsigned char ControllerNumber; + DAC960_V1_CommandMailbox_T CommandMailbox; + int DataTransferLength; + void *DataTransferBuffer; + DAC960_V1_DCDB_T *DCDB; + DAC960_V1_CommandStatus_T CommandStatus; + void (*CompletionFunction)(struct DAC960_V1_KernelCommand *); + void *CompletionData; +} +DAC960_V1_KernelCommand_T; + + +/* + Define the User Mode DAC960_IOCTL_V2_EXECUTE_COMMAND request structure. +*/ + +typedef struct DAC960_V2_UserCommand +{ + unsigned char ControllerNumber; + DAC960_V2_CommandMailbox_T CommandMailbox; + int DataTransferLength; + int RequestSenseLength; + void *DataTransferBuffer; + void *RequestSenseBuffer; +} +DAC960_V2_UserCommand_T; + + +/* + Define the Kernel Mode DAC960_IOCTL_V2_EXECUTE_COMMAND request structure. +*/ + +typedef struct DAC960_V2_KernelCommand +{ + unsigned char ControllerNumber; + DAC960_V2_CommandMailbox_T CommandMailbox; + int DataTransferLength; + int RequestSenseLength; + void *DataTransferBuffer; + void *RequestSenseBuffer; + DAC960_V2_CommandStatus_T CommandStatus; + void (*CompletionFunction)(struct DAC960_V2_KernelCommand *); + void *CompletionData; +} +DAC960_V2_KernelCommand_T; + + +/* + Define the User Mode DAC960_IOCTL_V2_GET_HEALTH_STATUS request structure. +*/ + +typedef struct DAC960_V2_GetHealthStatus +{ + unsigned char ControllerNumber; + DAC960_V2_HealthStatusBuffer_T *HealthStatusBuffer; +} +DAC960_V2_GetHealthStatus_T; + + +/* + Import the Kernel Mode IOCTL interface. +*/ + +extern int DAC960_KernelIOCTL(unsigned int Request, void *Argument); + + +/* + Virtual_to_Bus maps from Kernel Virtual Addresses to PCI Bus Addresses. +*/ + +static inline DAC960_BusAddress32_T Virtual_to_Bus(void *VirtualAddress) +{ + return (DAC960_BusAddress32_T) virt_to_bus(VirtualAddress); +} + + +/* + Bus_to_Virtual maps from PCI Bus Addresses to Kernel Virtual Addresses. +*/ + +static inline void *Bus_to_Virtual(DAC960_BusAddress32_T BusAddress) +{ + return (void *) bus_to_virt(BusAddress); +} + + +/* + DAC960_DriverVersion protects the private portion of this file. +*/ + +#ifdef DAC960_DriverVersion + + +/* + Define the maximum Driver Queue Depth and Controller Queue Depth supported + by DAC960 V1 and V2 Firmware Controllers. +*/ + +#define DAC960_MaxDriverQueueDepth 511 +#define DAC960_MaxControllerQueueDepth 512 + + +/* + Define the maximum number of Scatter/Gather Segments supported for any + DAC960 V1 and V2 Firmware controller. +*/ + +#define DAC960_V1_ScatterGatherLimit 33 +#define DAC960_V2_ScatterGatherLimit 128 + + +/* + Define the number of Command Mailboxes and Status Mailboxes used by the + DAC960 V1 and V2 Firmware Memory Mailbox Interface. +*/ + +#define DAC960_V1_CommandMailboxCount 256 +#define DAC960_V1_StatusMailboxCount 1024 +#define DAC960_V2_CommandMailboxCount 512 +#define DAC960_V2_StatusMailboxCount 512 + + +/* + Define the DAC960 Controller Monitoring Timer Interval. +*/ + +#define DAC960_MonitoringTimerInterval (10 * HZ) + + +/* + Define the DAC960 Controller Secondary Monitoring Interval. +*/ + +#define DAC960_SecondaryMonitoringInterval (60 * HZ) + + +/* + Define the DAC960 Controller Health Status Monitoring Interval. +*/ + +#define DAC960_HealthStatusMonitoringInterval (1 * HZ) + + +/* + Define the DAC960 Controller Progress Reporting Interval. +*/ + +#define DAC960_ProgressReportingInterval (60 * HZ) + + +/* + Define the maximum number of Partitions allowed for each Logical Drive. +*/ + +#define DAC960_MaxPartitions 8 +#define DAC960_MaxPartitionsBits 3 + + +/* + Define macros to extract the Controller Number, Logical Drive Number, and + Partition Number from a Kernel Device, and to construct a Major Number, Minor + Number, and Kernel Device from the Controller Number, Logical Drive Number, + and Partition Number. There is one Major Number assigned to each Controller. + The associated Minor Number is divided into the Logical Drive Number and + Partition Number. +*/ + +#define DAC960_ControllerNumber(Device) \ + (MAJOR(Device) - DAC960_MAJOR) + +#define DAC960_LogicalDriveNumber(Device) \ + (MINOR(Device) >> DAC960_MaxPartitionsBits) + +#define DAC960_PartitionNumber(Device) \ + (MINOR(Device) & (DAC960_MaxPartitions - 1)) + +#define DAC960_MajorNumber(ControllerNumber) \ + (DAC960_MAJOR + (ControllerNumber)) + +#define DAC960_MinorNumber(LogicalDriveNumber, PartitionNumber) \ + (((LogicalDriveNumber) << DAC960_MaxPartitionsBits) | (PartitionNumber)) + +#define DAC960_MinorCount (DAC960_MaxLogicalDrives \ + * DAC960_MaxPartitions) + +#define DAC960_KernelDevice(ControllerNumber, \ + LogicalDriveNumber, \ + PartitionNumber) \ + MKDEV(DAC960_MajorNumber(ControllerNumber), \ + DAC960_MinorNumber(LogicalDriveNumber, PartitionNumber)) + + +/* + Define the DAC960 Controller fixed Block Size and Block Size Bits. +*/ + +#define DAC960_BlockSize 512 #define DAC960_BlockSizeBits 9 /* - Define the Controller Line Buffer, Status Buffer, Rebuild Progress, - and User Message Sizes. + Define the number of Command structures that should be allocated as a + group to optimize kernel memory allocation. +*/ + +#define DAC960_V1_CommandAllocationGroupSize 11 +#define DAC960_V2_CommandAllocationGroupSize 29 + + +/* + Define the Controller Line Buffer, Progress Buffer, User Message, and + Initial Status Buffer sizes. */ #define DAC960_LineBufferSize 100 -#define DAC960_StatusBufferSize 16384 -#define DAC960_RebuildProgressSize 200 +#define DAC960_ProgressBufferSize 200 #define DAC960_UserMessageSize 200 +#define DAC960_InitialStatusBufferSize (8192-32) + + +/* + Define the DAC960 Controller Firmware Types. +*/ + +typedef enum +{ + DAC960_V1_Controller = 1, + DAC960_V2_Controller = 2 +} +DAC960_FirmwareType_T; /* - Define the types of DAC960 Controllers that are supported. + Define the DAC960 Controller Hardware Types. */ typedef enum { - DAC960_V5_Controller = 1, /* DAC1164P */ - DAC960_V4_Controller = 2, /* DAC960PTL/PJ/PG */ - DAC960_V3_Controller = 3 /* DAC960PU/PD/PL */ + DAC960_BA_Controller = 1, /* eXtremeRAID 2000 */ + DAC960_LP_Controller = 2, /* AcceleRAID 352 */ + DAC960_LA_Controller = 3, /* DAC1164P */ + DAC960_PG_Controller = 4, /* DAC960PTL/PJ/PG */ + DAC960_PD_Controller = 5 /* DAC960PU/PD/PL */ } -DAC960_ControllerType_T; +DAC960_HardwareType_T; /* @@ -1111,18 +2150,21 @@ typedef struct buffer_head BufferHeader_T; typedef struct file File_T; +typedef struct block_device_operations BlockDeviceOperations_T; typedef struct gendisk GenericDiskInfo_T; typedef struct hd_geometry DiskGeometry_T; typedef struct hd_struct DiskPartition_T; typedef struct inode Inode_T; typedef struct inode_operations InodeOperations_T; typedef kdev_t KernelDevice_T; +typedef struct list_head ListHead_T; typedef struct notifier_block NotifierBlock_T; typedef struct pci_dev PCI_Device_T; typedef struct proc_dir_entry PROC_DirectoryEntry_T; typedef unsigned long ProcessorFlags_T; typedef struct pt_regs Registers_T; typedef struct request IO_Request_T; +typedef request_queue_t RequestQueue_T; typedef struct semaphore Semaphore_T; typedef struct super_block SuperBlock_T; typedef struct timer_list Timer_T; @@ -1130,281 +2172,996 @@ /* - Define the DAC960 Controller Status Mailbox structure. + Define the DAC960 V1 Firmware Controller Status Mailbox structure. +*/ + +typedef union DAC960_V1_StatusMailbox +{ + unsigned int Word; /* Word 0 */ + struct { + DAC960_V1_CommandIdentifier_T CommandIdentifier; /* Byte 0 */ + unsigned char :7; /* Byte 1 Bits 0-6 */ + boolean Valid:1; /* Byte 1 Bit 7 */ + DAC960_V1_CommandStatus_T CommandStatus; /* Bytes 2-3 */ + } Fields; +} +DAC960_V1_StatusMailbox_T; + + +/* + Define the DAC960 V2 Firmware Controller Status Mailbox structure. +*/ + +typedef union DAC960_V2_StatusMailbox +{ + unsigned int Words[2]; /* Words 0-1 */ + struct { + DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */ + DAC960_V2_CommandStatus_T CommandStatus; /* Byte 2 */ + unsigned char RequestSenseLength; /* Byte 3 */ + int DataTransferResidue; /* Bytes 4-7 */ + } Fields; +} +DAC960_V2_StatusMailbox_T; + + +/* + Define the DAC960 Driver Command Types. +*/ + +typedef enum +{ + DAC960_ReadCommand = 1, + DAC960_WriteCommand = 2, + DAC960_ReadRetryCommand = 3, + DAC960_WriteRetryCommand = 4, + DAC960_MonitoringCommand = 5, + DAC960_ImmediateCommand = 6, + DAC960_QueuedCommand = 7 +} +DAC960_CommandType_T; + + +/* + Define the DAC960 Driver Command structure. +*/ + +typedef struct DAC960_Command +{ + int CommandIdentifier; + DAC960_CommandType_T CommandType; + struct DAC960_Controller *Controller; + struct DAC960_Command *Next; + Semaphore_T *Semaphore; + unsigned int LogicalDriveNumber; + unsigned int BlockNumber; + unsigned int BlockCount; + unsigned int SegmentCount; + BufferHeader_T *BufferHeader; + void *RequestBuffer; + union { + struct { + DAC960_V1_CommandMailbox_T CommandMailbox; + DAC960_V1_KernelCommand_T *KernelCommand; + DAC960_V1_CommandStatus_T CommandStatus; + DAC960_V1_ScatterGatherSegment_T + ScatterGatherList[DAC960_V1_ScatterGatherLimit] + __attribute__ ((aligned (sizeof(DAC960_V1_ScatterGatherSegment_T)))); + unsigned int EndMarker[0]; + } V1; + struct { + DAC960_V2_CommandMailbox_T CommandMailbox; + DAC960_V2_KernelCommand_T *KernelCommand; + DAC960_V2_CommandStatus_T CommandStatus; + unsigned char RequestSenseLength; + int DataTransferResidue; + DAC960_V2_ScatterGatherSegment_T + ScatterGatherList[DAC960_V2_ScatterGatherLimit] + __attribute__ ((aligned (sizeof(DAC960_V2_ScatterGatherSegment_T)))); + DAC960_SCSI_RequestSense_T RequestSense + __attribute__ ((aligned (sizeof(int)))); + unsigned int EndMarker[0]; + } V2; + } FW; +} +DAC960_Command_T; + + +/* + Define the DAC960 Driver Controller structure. +*/ + +typedef struct DAC960_Controller +{ + void *BaseAddress; + void *MemoryMappedAddress; + DAC960_FirmwareType_T FirmwareType; + DAC960_HardwareType_T HardwareType; + DAC960_IO_Address_T IO_Address; + DAC960_PCI_Address_T PCI_Address; + unsigned char ControllerNumber; + unsigned char ControllerName[4]; + unsigned char ModelName[20]; + unsigned char FullModelName[28]; + unsigned char FirmwareVersion[12]; + unsigned char Bus; + unsigned char Device; + unsigned char Function; + unsigned char IRQ_Channel; + unsigned char Channels; + unsigned char Targets; + unsigned char MemorySize; + unsigned char LogicalDriveCount; + unsigned short CommandAllocationGroupSize; + unsigned short ControllerQueueDepth; + unsigned short DriverQueueDepth; + unsigned short MaxBlocksPerCommand; + unsigned short ControllerScatterGatherLimit; + unsigned short DriverScatterGatherLimit; + unsigned int ControllerUsageCount; + unsigned int CombinedStatusBufferLength; + unsigned int InitialStatusLength; + unsigned int CurrentStatusLength; + unsigned int ProgressBufferLength; + unsigned int UserStatusLength; + unsigned long MemoryMailboxPagesAddress; + unsigned long MemoryMailboxPagesOrder; + unsigned long MonitoringTimerCount; + unsigned long PrimaryMonitoringTime; + unsigned long SecondaryMonitoringTime; + unsigned long LastProgressReportTime; + unsigned long LastCurrentStatusTime; + boolean ControllerDetectionSuccessful; + boolean ControllerInitialized; + boolean MonitoringCommandDeferred; + boolean EphemeralProgressMessage; + boolean DriveSpinUpMessageDisplayed; + boolean MonitoringAlertMode; + Timer_T MonitoringTimer; + GenericDiskInfo_T GenericDiskInfo; + DAC960_Command_T *FreeCommands; + unsigned char *CombinedStatusBuffer; + unsigned char *CurrentStatusBuffer; + RequestQueue_T *RequestQueue; + WaitQueue_T CommandWaitQueue; + WaitQueue_T HealthStatusWaitQueue; + DAC960_Command_T InitialCommand; + DAC960_Command_T *Commands[DAC960_MaxDriverQueueDepth]; + PROC_DirectoryEntry_T *ControllerProcEntry; + unsigned int LogicalDriveUsageCount[DAC960_MaxLogicalDrives]; + boolean LogicalDriveInitiallyAccessible[DAC960_MaxLogicalDrives]; + void (*QueueCommand)(DAC960_Command_T *Command); + boolean (*ReadControllerConfiguration)(struct DAC960_Controller *); + boolean (*ReadDeviceConfiguration)(struct DAC960_Controller *); + boolean (*ReportDeviceConfiguration)(struct DAC960_Controller *); + void (*QueueReadWriteCommand)(DAC960_Command_T *Command); + union { + struct { + unsigned char GeometryTranslationHeads; + unsigned char GeometryTranslationSectors; + unsigned char PendingRebuildFlag; + unsigned short StripeSize; + unsigned short SegmentSize; + unsigned short NewEventLogSequenceNumber; + unsigned short OldEventLogSequenceNumber; + unsigned short DeviceStateChannel; + unsigned short DeviceStateTargetID; + boolean DualModeMemoryMailboxInterface; + boolean SAFTE_EnclosureManagementEnabled; + boolean NeedLogicalDriveInformation; + boolean NeedErrorTableInformation; + boolean NeedDeviceStateInformation; + boolean NeedDeviceInquiryInformation; + boolean NeedDeviceSerialNumberInformation; + boolean NeedRebuildProgress; + boolean NeedConsistencyCheckProgress; + boolean RebuildProgressFirst; + boolean RebuildFlagPending; + boolean RebuildStatusPending; + DAC960_V1_CommandMailbox_T *FirstCommandMailbox; + DAC960_V1_CommandMailbox_T *LastCommandMailbox; + DAC960_V1_CommandMailbox_T *NextCommandMailbox; + DAC960_V1_CommandMailbox_T *PreviousCommandMailbox1; + DAC960_V1_CommandMailbox_T *PreviousCommandMailbox2; + DAC960_V1_StatusMailbox_T *FirstStatusMailbox; + DAC960_V1_StatusMailbox_T *LastStatusMailbox; + DAC960_V1_StatusMailbox_T *NextStatusMailbox; + DAC960_V1_DCDB_T MonitoringDCDB; + DAC960_V1_Enquiry_T Enquiry; + DAC960_V1_Enquiry_T NewEnquiry; + DAC960_V1_ErrorTable_T ErrorTable; + DAC960_V1_ErrorTable_T NewErrorTable; + DAC960_V1_EventLogEntry_T EventLogEntry; + DAC960_V1_RebuildProgress_T RebuildProgress; + DAC960_V1_CommandStatus_T LastRebuildStatus; + DAC960_V1_CommandStatus_T PendingRebuildStatus; + DAC960_V1_LogicalDriveInformationArray_T LogicalDriveInformation; + DAC960_V1_LogicalDriveInformationArray_T NewLogicalDriveInformation; + DAC960_V1_DeviceState_T + DeviceState[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets]; + DAC960_V1_DeviceState_T NewDeviceState; + DAC960_SCSI_Inquiry_T + InquiryStandardData[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets]; + DAC960_SCSI_Inquiry_UnitSerialNumber_T + InquiryUnitSerialNumber[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets]; + int DeviceResetCount[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets]; + boolean DirectCommandActive[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets]; + } V1; + struct { + unsigned int StatusChangeCounter; + unsigned int NextEventSequenceNumber; + unsigned int PhysicalDeviceIndex; + boolean NeedLogicalDeviceInformation; + boolean NeedPhysicalDeviceInformation; + boolean NeedDeviceSerialNumberInformation; + DAC960_V2_CommandMailbox_T *FirstCommandMailbox; + DAC960_V2_CommandMailbox_T *LastCommandMailbox; + DAC960_V2_CommandMailbox_T *NextCommandMailbox; + DAC960_V2_CommandMailbox_T *PreviousCommandMailbox1; + DAC960_V2_CommandMailbox_T *PreviousCommandMailbox2; + DAC960_V2_StatusMailbox_T *FirstStatusMailbox; + DAC960_V2_StatusMailbox_T *LastStatusMailbox; + DAC960_V2_StatusMailbox_T *NextStatusMailbox; + DAC960_V2_HealthStatusBuffer_T *HealthStatusBuffer; + DAC960_V2_ControllerInfo_T ControllerInformation; + DAC960_V2_ControllerInfo_T NewControllerInformation; + DAC960_V2_LogicalDeviceInfo_T + *LogicalDeviceInformation[DAC960_MaxLogicalDrives]; + DAC960_V2_LogicalDeviceInfo_T NewLogicalDeviceInformation; + DAC960_V2_PhysicalDeviceInfo_T + *PhysicalDeviceInformation[DAC960_V2_MaxPhysicalDevices]; + DAC960_V2_PhysicalDeviceInfo_T NewPhysicalDeviceInformation; + DAC960_SCSI_Inquiry_UnitSerialNumber_T + *InquiryUnitSerialNumber[DAC960_V2_MaxPhysicalDevices]; + DAC960_V2_PhysicalDevice_T + LogicalDriveToVirtualDevice[DAC960_MaxLogicalDrives]; + DAC960_V2_Event_T Event; + } V2; + } FW; + DiskPartition_T DiskPartitions[DAC960_MinorCount]; + int PartitionSizes[DAC960_MinorCount]; + int BlockSizes[DAC960_MinorCount]; + int MaxSectorsPerRequest[DAC960_MinorCount]; + unsigned char ProgressBuffer[DAC960_ProgressBufferSize]; + unsigned char UserStatusBuffer[DAC960_UserMessageSize]; +} +DAC960_Controller_T; + + +/* + Simplify access to Firmware Version Dependent Data Structure Components + and Functions. +*/ + +#define V1 FW.V1 +#define V2 FW.V2 +#define DAC960_QueueCommand(Command) \ + (Controller->QueueCommand)(Command) +#define DAC960_ReadControllerConfiguration(Controller) \ + (Controller->ReadControllerConfiguration)(Controller) +#define DAC960_ReadDeviceConfiguration(Controller) \ + (Controller->ReadDeviceConfiguration)(Controller) +#define DAC960_ReportDeviceConfiguration(Controller) \ + (Controller->ReportDeviceConfiguration)(Controller) +#define DAC960_QueueReadWriteCommand(Command) \ + (Controller->QueueReadWriteCommand)(Command) + + +/* + DAC960_AcquireControllerLock acquires exclusive access to Controller. +*/ + +static inline +void DAC960_AcquireControllerLock(DAC960_Controller_T *Controller, + ProcessorFlags_T *ProcessorFlags) +{ + spin_lock_irqsave(&io_request_lock, *ProcessorFlags); +} + + +/* + DAC960_ReleaseControllerLock releases exclusive access to Controller. +*/ + +static inline +void DAC960_ReleaseControllerLock(DAC960_Controller_T *Controller, + ProcessorFlags_T *ProcessorFlags) +{ + spin_unlock_irqrestore(&io_request_lock, *ProcessorFlags); +} + + +/* + DAC960_AcquireControllerLockRF acquires exclusive access to Controller, + but is only called from the request function with the io_request_lock held. +*/ + +static inline +void DAC960_AcquireControllerLockRF(DAC960_Controller_T *Controller, + ProcessorFlags_T *ProcessorFlags) +{ +} + + +/* + DAC960_ReleaseControllerLockRF releases exclusive access to Controller, + but is only called from the request function with the io_request_lock held. +*/ + +static inline +void DAC960_ReleaseControllerLockRF(DAC960_Controller_T *Controller, + ProcessorFlags_T *ProcessorFlags) +{ +} + + +/* + DAC960_AcquireControllerLockIH acquires exclusive access to Controller, + but is only called from the interrupt handler. +*/ + +static inline +void DAC960_AcquireControllerLockIH(DAC960_Controller_T *Controller, + ProcessorFlags_T *ProcessorFlags) +{ + spin_lock_irqsave(&io_request_lock, *ProcessorFlags); +} + + +/* + DAC960_ReleaseControllerLockIH releases exclusive access to Controller, + but is only called from the interrupt handler. +*/ + +static inline +void DAC960_ReleaseControllerLockIH(DAC960_Controller_T *Controller, + ProcessorFlags_T *ProcessorFlags) +{ + spin_unlock_irqrestore(&io_request_lock, *ProcessorFlags); +} + + +/* + Define the DAC960 BA Series Controller Interface Register Offsets. +*/ + +#define DAC960_BA_RegisterWindowSize 0x80 + +typedef enum +{ + DAC960_BA_InboundDoorBellRegisterOffset = 0x60, + DAC960_BA_OutboundDoorBellRegisterOffset = 0x61, + DAC960_BA_InterruptStatusRegisterOffset = 0x30, + DAC960_BA_InterruptMaskRegisterOffset = 0x34, + DAC960_BA_CommandMailboxBusAddressOffset = 0x50, + DAC960_BA_CommandStatusOffset = 0x58, + DAC960_BA_ErrorStatusRegisterOffset = 0x63 +} +DAC960_BA_RegisterOffsets_T; + + +/* + Define the structure of the DAC960 BA Series Inbound Door Bell Register. +*/ + +typedef union DAC960_BA_InboundDoorBellRegister +{ + unsigned char All; + struct { + boolean HardwareMailboxNewCommand:1; /* Bit 0 */ + boolean AcknowledgeHardwareMailboxStatus:1; /* Bit 1 */ + boolean GenerateInterrupt:1; /* Bit 2 */ + boolean ControllerReset:1; /* Bit 3 */ + boolean MemoryMailboxNewCommand:1; /* Bit 4 */ + unsigned char :3; /* Bits 5-7 */ + } Write; + struct { + boolean HardwareMailboxEmpty:1; /* Bit 0 */ + boolean InitializationNotInProgress:1; /* Bit 1 */ + unsigned char :6; /* Bits 2-7 */ + } Read; +} +DAC960_BA_InboundDoorBellRegister_T; + + +/* + Define the structure of the DAC960 BA Series Outbound Door Bell Register. +*/ + +typedef union DAC960_BA_OutboundDoorBellRegister +{ + unsigned char All; + struct { + boolean AcknowledgeHardwareMailboxInterrupt:1; /* Bit 0 */ + boolean AcknowledgeMemoryMailboxInterrupt:1; /* Bit 1 */ + unsigned char :6; /* Bits 2-7 */ + } Write; + struct { + boolean HardwareMailboxStatusAvailable:1; /* Bit 0 */ + boolean MemoryMailboxStatusAvailable:1; /* Bit 1 */ + unsigned char :6; /* Bits 2-7 */ + } Read; +} +DAC960_BA_OutboundDoorBellRegister_T; + + +/* + Define the structure of the DAC960 BA Series Interrupt Mask Register. +*/ + +typedef union DAC960_BA_InterruptMaskRegister +{ + unsigned char All; + struct { + unsigned int :2; /* Bits 0-1 */ + boolean DisableInterrupts:1; /* Bit 2 */ + boolean DisableInterruptsI2O:1; /* Bit 3 */ + unsigned int :4; /* Bits 4-7 */ + } Bits; +} +DAC960_BA_InterruptMaskRegister_T; + + +/* + Define the structure of the DAC960 BA Series Error Status Register. +*/ + +typedef union DAC960_BA_ErrorStatusRegister +{ + unsigned char All; + struct { + unsigned int :2; /* Bits 0-1 */ + boolean ErrorStatusPending:1; /* Bit 2 */ + unsigned int :5; /* Bits 3-7 */ + } Bits; +} +DAC960_BA_ErrorStatusRegister_T; + + +/* + Define inline functions to provide an abstraction for reading and writing the + DAC960 BA Series Controller Interface Registers. +*/ + +static inline +void DAC960_BA_HardwareMailboxNewCommand(void *ControllerBaseAddress) +{ + DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.HardwareMailboxNewCommand = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_BA_InboundDoorBellRegisterOffset); +} + +static inline +void DAC960_BA_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress) +{ + DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.AcknowledgeHardwareMailboxStatus = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_BA_InboundDoorBellRegisterOffset); +} + +static inline +void DAC960_BA_GenerateInterrupt(void *ControllerBaseAddress) +{ + DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.GenerateInterrupt = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_BA_InboundDoorBellRegisterOffset); +} + +static inline +void DAC960_BA_ControllerReset(void *ControllerBaseAddress) +{ + DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.ControllerReset = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_BA_InboundDoorBellRegisterOffset); +} + +static inline +void DAC960_BA_MemoryMailboxNewCommand(void *ControllerBaseAddress) +{ + DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.MemoryMailboxNewCommand = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_BA_InboundDoorBellRegisterOffset); +} + +static inline +boolean DAC960_BA_HardwareMailboxFullP(void *ControllerBaseAddress) +{ + DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_BA_InboundDoorBellRegisterOffset); + return !InboundDoorBellRegister.Read.HardwareMailboxEmpty; +} + +static inline +boolean DAC960_BA_InitializationInProgressP(void *ControllerBaseAddress) +{ + DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_BA_InboundDoorBellRegisterOffset); + return !InboundDoorBellRegister.Read.InitializationNotInProgress; +} + +static inline +void DAC960_BA_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) +{ + DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = 0; + OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true; + writeb(OutboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_BA_OutboundDoorBellRegisterOffset); +} + +static inline +void DAC960_BA_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress) +{ + DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = 0; + OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true; + writeb(OutboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_BA_OutboundDoorBellRegisterOffset); +} + +static inline +void DAC960_BA_AcknowledgeInterrupt(void *ControllerBaseAddress) +{ + DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = 0; + OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true; + OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true; + writeb(OutboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_BA_OutboundDoorBellRegisterOffset); +} + +static inline +boolean DAC960_BA_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress) +{ + DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_BA_OutboundDoorBellRegisterOffset); + return OutboundDoorBellRegister.Read.HardwareMailboxStatusAvailable; +} + +static inline +boolean DAC960_BA_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress) +{ + DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_BA_OutboundDoorBellRegisterOffset); + return OutboundDoorBellRegister.Read.MemoryMailboxStatusAvailable; +} + +static inline +void DAC960_BA_EnableInterrupts(void *ControllerBaseAddress) +{ + DAC960_BA_InterruptMaskRegister_T InterruptMaskRegister; + InterruptMaskRegister.All = 0xFF; + InterruptMaskRegister.Bits.DisableInterrupts = false; + InterruptMaskRegister.Bits.DisableInterruptsI2O = true; + writeb(InterruptMaskRegister.All, + ControllerBaseAddress + DAC960_BA_InterruptMaskRegisterOffset); +} + +static inline +void DAC960_BA_DisableInterrupts(void *ControllerBaseAddress) +{ + DAC960_BA_InterruptMaskRegister_T InterruptMaskRegister; + InterruptMaskRegister.All = 0xFF; + InterruptMaskRegister.Bits.DisableInterrupts = true; + InterruptMaskRegister.Bits.DisableInterruptsI2O = true; + writeb(InterruptMaskRegister.All, + ControllerBaseAddress + DAC960_BA_InterruptMaskRegisterOffset); +} + +static inline +boolean DAC960_BA_InterruptsEnabledP(void *ControllerBaseAddress) +{ + DAC960_BA_InterruptMaskRegister_T InterruptMaskRegister; + InterruptMaskRegister.All = + readb(ControllerBaseAddress + DAC960_BA_InterruptMaskRegisterOffset); + return !InterruptMaskRegister.Bits.DisableInterrupts; +} + +static inline +void DAC960_BA_WriteCommandMailbox(DAC960_V2_CommandMailbox_T + *MemoryCommandMailbox, + DAC960_V2_CommandMailbox_T + *CommandMailbox) +{ + memcpy(&MemoryCommandMailbox->Words[1], &CommandMailbox->Words[1], + sizeof(DAC960_V2_CommandMailbox_T) - sizeof(unsigned int)); + wmb(); + MemoryCommandMailbox->Words[0] = CommandMailbox->Words[0]; + mb(); +} + +static inline +void DAC960_BA_WriteHardwareMailbox(void *ControllerBaseAddress, + DAC960_V2_CommandMailbox_T *CommandMailbox) +{ + writel(Virtual_to_Bus(CommandMailbox), + ControllerBaseAddress + DAC960_BA_CommandMailboxBusAddressOffset); +} + +static inline DAC960_V2_CommandIdentifier_T +DAC960_BA_ReadCommandIdentifier(void *ControllerBaseAddress) +{ + return readw(ControllerBaseAddress + DAC960_BA_CommandStatusOffset); +} + +static inline DAC960_V2_CommandStatus_T +DAC960_BA_ReadCommandStatus(void *ControllerBaseAddress) +{ + return readw(ControllerBaseAddress + DAC960_BA_CommandStatusOffset + 2); +} + +static inline boolean +DAC960_BA_ReadErrorStatus(void *ControllerBaseAddress, + unsigned char *ErrorStatus, + unsigned char *Parameter0, + unsigned char *Parameter1) +{ + DAC960_BA_ErrorStatusRegister_T ErrorStatusRegister; + ErrorStatusRegister.All = + readb(ControllerBaseAddress + DAC960_BA_ErrorStatusRegisterOffset); + if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false; + ErrorStatusRegister.Bits.ErrorStatusPending = false; + *ErrorStatus = ErrorStatusRegister.All; + *Parameter0 = + readb(ControllerBaseAddress + DAC960_BA_CommandMailboxBusAddressOffset + 0); + *Parameter1 = + readb(ControllerBaseAddress + DAC960_BA_CommandMailboxBusAddressOffset + 1); + writeb(0xFF, ControllerBaseAddress + DAC960_BA_ErrorStatusRegisterOffset); + return true; +} + + +/* + Define the DAC960 LP Series Controller Interface Register Offsets. */ -typedef union DAC960_StatusMailbox +#define DAC960_LP_RegisterWindowSize 0x80 + +typedef enum { - unsigned int Word; /* Bytes 0-3 */ - struct { - DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 0 */ - unsigned char :7; /* Byte 1 Bits 0-6 */ - boolean Valid:1; /* Byte 1 Bit 7 */ - DAC960_CommandStatus_T CommandStatus; /* Bytes 2-3 */ - } Fields; + DAC960_LP_InboundDoorBellRegisterOffset = 0x20, + DAC960_LP_OutboundDoorBellRegisterOffset = 0x2C, + DAC960_LP_InterruptStatusRegisterOffset = 0x30, + DAC960_LP_InterruptMaskRegisterOffset = 0x34, + DAC960_LP_CommandMailboxBusAddressOffset = 0x10, + DAC960_LP_CommandStatusOffset = 0x18, + DAC960_LP_ErrorStatusRegisterOffset = 0x2E } -DAC960_StatusMailbox_T; +DAC960_LP_RegisterOffsets_T; /* - Define the DAC960 Driver Command Types. + Define the structure of the DAC960 LP Series Inbound Door Bell Register. */ -typedef enum +typedef union DAC960_LP_InboundDoorBellRegister { - DAC960_ReadCommand = 1, - DAC960_WriteCommand = 2, - DAC960_ReadRetryCommand = 3, - DAC960_WriteRetryCommand = 4, - DAC960_MonitoringCommand = 5, - DAC960_ImmediateCommand = 6, - DAC960_QueuedCommand = 7 + unsigned char All; + struct { + boolean HardwareMailboxNewCommand:1; /* Bit 0 */ + boolean AcknowledgeHardwareMailboxStatus:1; /* Bit 1 */ + boolean GenerateInterrupt:1; /* Bit 2 */ + boolean ControllerReset:1; /* Bit 3 */ + boolean MemoryMailboxNewCommand:1; /* Bit 4 */ + unsigned char :3; /* Bits 5-7 */ + } Write; + struct { + boolean HardwareMailboxFull:1; /* Bit 0 */ + boolean InitializationInProgress:1; /* Bit 1 */ + unsigned char :6; /* Bits 2-7 */ + } Read; } -DAC960_CommandType_T; +DAC960_LP_InboundDoorBellRegister_T; /* - Define the DAC960 Driver Command structure. + Define the structure of the DAC960 LP Series Outbound Door Bell Register. */ -typedef struct DAC960_Command +typedef union DAC960_LP_OutboundDoorBellRegister { - DAC960_CommandType_T CommandType; - DAC960_CommandMailbox_T CommandMailbox; - DAC960_CommandStatus_T CommandStatus; - struct DAC960_Controller *Controller; - struct DAC960_Command *Next; - Semaphore_T *Semaphore; - unsigned int LogicalDriveNumber; - unsigned int BlockNumber; - unsigned int BlockCount; - unsigned int SegmentCount; - BufferHeader_T *BufferHeader; - DAC960_KernelCommand_T *KernelCommand; - DAC960_ScatterGatherSegment_T - ScatterGatherList[DAC960_MaxScatterGatherSegments]; + unsigned char All; + struct { + boolean AcknowledgeHardwareMailboxInterrupt:1; /* Bit 0 */ + boolean AcknowledgeMemoryMailboxInterrupt:1; /* Bit 1 */ + unsigned char :6; /* Bits 2-7 */ + } Write; + struct { + boolean HardwareMailboxStatusAvailable:1; /* Bit 0 */ + boolean MemoryMailboxStatusAvailable:1; /* Bit 1 */ + unsigned char :6; /* Bits 2-7 */ + } Read; } -DAC960_Command_T; +DAC960_LP_OutboundDoorBellRegister_T; /* - Define the DAC960 Driver Controller structure. + Define the structure of the DAC960 LP Series Interrupt Mask Register. */ -typedef struct DAC960_Controller +typedef union DAC960_LP_InterruptMaskRegister { - void *BaseAddress; - void *MemoryMappedAddress; - DAC960_ControllerType_T ControllerType; - DAC960_IO_Address_T IO_Address; - DAC960_PCI_Address_T PCI_Address; - unsigned char ControllerNumber; - unsigned char ControllerName[4]; - unsigned char ModelName[12]; - unsigned char FullModelName[18]; - unsigned char FirmwareVersion[14]; - unsigned char Bus; - unsigned char Device; - unsigned char Function; - unsigned char IRQ_Channel; - unsigned char Channels; - unsigned char MemorySize; - unsigned char LogicalDriveCount; - unsigned char GeometryTranslationHeads; - unsigned char GeometryTranslationSectors; - unsigned char PendingRebuildFlag; - unsigned short ControllerQueueDepth; - unsigned short DriverQueueDepth; - unsigned short MaxBlocksPerCommand; - unsigned short MaxScatterGatherSegments; - unsigned short StripeSize; - unsigned short SegmentSize; - unsigned short NewEventLogSequenceNumber; - unsigned short OldEventLogSequenceNumber; - unsigned short InitialStatusLength; - unsigned short CurrentStatusLength; - unsigned short UserStatusLength; - unsigned short RebuildProgressLength; - unsigned int ControllerUsageCount; - unsigned int EnquiryIndex; - unsigned int LogicalDriveInformationIndex; - unsigned int ErrorTableIndex; - unsigned int DeviceStateIndex; - unsigned int DeviceStateChannel; - unsigned int DeviceStateTargetID; - unsigned long MonitoringTimerCount; - unsigned long SecondaryMonitoringTime; - unsigned long LastProgressReportTime; - unsigned long LastCurrentStatusTime; - boolean DualModeMemoryMailboxInterface; - boolean SAFTE_EnclosureManagementEnabled; - boolean ControllerInitialized; - boolean MonitoringCommandDeferred; - boolean NeedLogicalDriveInformation; - boolean NeedErrorTableInformation; - boolean NeedDeviceStateInformation; - boolean NeedDeviceInquiryInformation; - boolean NeedDeviceSerialNumberInformation; - boolean NeedRebuildProgress; - boolean NeedConsistencyCheckProgress; - boolean EphemeralProgressMessage; - boolean RebuildFlagPending; - boolean RebuildStatusPending; - boolean DriveSpinUpMessageDisplayed; - Timer_T MonitoringTimer; - GenericDiskInfo_T GenericDiskInfo; - DAC960_Command_T *FreeCommands; - DAC960_CommandMailbox_T *FirstCommandMailbox; - DAC960_CommandMailbox_T *LastCommandMailbox; - DAC960_CommandMailbox_T *NextCommandMailbox; - DAC960_CommandMailbox_T *PreviousCommandMailbox1; - DAC960_CommandMailbox_T *PreviousCommandMailbox2; - DAC960_StatusMailbox_T *FirstStatusMailbox; - DAC960_StatusMailbox_T *LastStatusMailbox; - DAC960_StatusMailbox_T *NextStatusMailbox; - WaitQueue_T CommandWaitQueue; - DAC960_DCDB_T MonitoringDCDB; - DAC960_Enquiry_T Enquiry[2]; - DAC960_ErrorTable_T ErrorTable[2]; - DAC960_EventLogEntry_T EventLogEntry; - DAC960_RebuildProgress_T RebuildProgress; - DAC960_CommandStatus_T LastRebuildStatus; - DAC960_CommandStatus_T PendingRebuildStatus; - DAC960_LogicalDriveInformation_T - LogicalDriveInformation[2][DAC960_MaxLogicalDrives]; - DAC960_LogicalDriveState_T LogicalDriveInitialState[DAC960_MaxLogicalDrives]; - DAC960_DeviceState_T DeviceState[2][DAC960_MaxChannels][DAC960_MaxTargets]; - DAC960_Command_T Commands[DAC960_MaxDriverQueueDepth]; - DAC960_SCSI_Inquiry_T - InquiryStandardData[DAC960_MaxChannels][DAC960_MaxTargets]; - DAC960_SCSI_Inquiry_UnitSerialNumber_T - InquiryUnitSerialNumber[DAC960_MaxChannels][DAC960_MaxTargets]; - DiskPartition_T DiskPartitions[DAC960_MinorCount]; - int LogicalDriveUsageCount[DAC960_MaxLogicalDrives]; - int PartitionSizes[DAC960_MinorCount]; - int BlockSizes[DAC960_MinorCount]; - int MaxSectorsPerRequest[DAC960_MinorCount]; - int MaxSegmentsPerRequest[DAC960_MinorCount]; - int DeviceResetCount[DAC960_MaxChannels][DAC960_MaxTargets]; - boolean DirectCommandActive[DAC960_MaxChannels][DAC960_MaxTargets]; - char InitialStatusBuffer[DAC960_StatusBufferSize]; - char CurrentStatusBuffer[DAC960_StatusBufferSize]; - char UserStatusBuffer[DAC960_UserMessageSize]; - char RebuildProgressBuffer[DAC960_RebuildProgressSize]; + unsigned char All; + struct { + unsigned int :2; /* Bits 0-1 */ + boolean DisableInterrupts:1; /* Bit 2 */ + unsigned int :5; /* Bits 3-7 */ + } Bits; } -DAC960_Controller_T; +DAC960_LP_InterruptMaskRegister_T; /* - DAC960_AcquireControllerLock acquires exclusive access to Controller. + Define the structure of the DAC960 LP Series Error Status Register. */ -static inline -void DAC960_AcquireControllerLock(DAC960_Controller_T *Controller, - ProcessorFlags_T *ProcessorFlags) +typedef union DAC960_LP_ErrorStatusRegister { - spin_lock_irqsave(&io_request_lock, *ProcessorFlags); + unsigned char All; + struct { + unsigned int :2; /* Bits 0-1 */ + boolean ErrorStatusPending:1; /* Bit 2 */ + unsigned int :5; /* Bits 3-7 */ + } Bits; } +DAC960_LP_ErrorStatusRegister_T; /* - DAC960_ReleaseControllerLock releases exclusive access to Controller. + Define inline functions to provide an abstraction for reading and writing the + DAC960 LP Series Controller Interface Registers. */ static inline -void DAC960_ReleaseControllerLock(DAC960_Controller_T *Controller, - ProcessorFlags_T *ProcessorFlags) +void DAC960_LP_HardwareMailboxNewCommand(void *ControllerBaseAddress) { - spin_unlock_irqrestore(&io_request_lock, *ProcessorFlags); + DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.HardwareMailboxNewCommand = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_LP_InboundDoorBellRegisterOffset); } +static inline +void DAC960_LP_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress) +{ + DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.AcknowledgeHardwareMailboxStatus = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_LP_InboundDoorBellRegisterOffset); +} -/* - DAC960_AcquireControllerLockRF acquires exclusive access to Controller, - but is only called from the request function with the io_request_lock held. -*/ +static inline +void DAC960_LP_GenerateInterrupt(void *ControllerBaseAddress) +{ + DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.GenerateInterrupt = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_LP_InboundDoorBellRegisterOffset); +} static inline -void DAC960_AcquireControllerLockRF(DAC960_Controller_T *Controller, - ProcessorFlags_T *ProcessorFlags) +void DAC960_LP_ControllerReset(void *ControllerBaseAddress) { + DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.ControllerReset = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_LP_InboundDoorBellRegisterOffset); } +static inline +void DAC960_LP_MemoryMailboxNewCommand(void *ControllerBaseAddress) +{ + DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.MemoryMailboxNewCommand = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_LP_InboundDoorBellRegisterOffset); +} -/* - DAC960_ReleaseControllerLockRF releases exclusive access to Controller, - but is only called from the request function with the io_request_lock held. -*/ +static inline +boolean DAC960_LP_HardwareMailboxFullP(void *ControllerBaseAddress) +{ + DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_LP_InboundDoorBellRegisterOffset); + return InboundDoorBellRegister.Read.HardwareMailboxFull; +} static inline -void DAC960_ReleaseControllerLockRF(DAC960_Controller_T *Controller, - ProcessorFlags_T *ProcessorFlags) +boolean DAC960_LP_InitializationInProgressP(void *ControllerBaseAddress) { + DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_LP_InboundDoorBellRegisterOffset); + return InboundDoorBellRegister.Read.InitializationInProgress; } +static inline +void DAC960_LP_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) +{ + DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = 0; + OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true; + writeb(OutboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_LP_OutboundDoorBellRegisterOffset); +} -/* - DAC960_AcquireControllerLockIH acquires exclusive access to Controller, - but is only called from the interrupt handler. -*/ +static inline +void DAC960_LP_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress) +{ + DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = 0; + OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true; + writeb(OutboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_LP_OutboundDoorBellRegisterOffset); +} static inline -void DAC960_AcquireControllerLockIH(DAC960_Controller_T *Controller, - ProcessorFlags_T *ProcessorFlags) +void DAC960_LP_AcknowledgeInterrupt(void *ControllerBaseAddress) { - spin_lock_irqsave(&io_request_lock, *ProcessorFlags); + DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = 0; + OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true; + OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true; + writeb(OutboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_LP_OutboundDoorBellRegisterOffset); } +static inline +boolean DAC960_LP_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress) +{ + DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_LP_OutboundDoorBellRegisterOffset); + return OutboundDoorBellRegister.Read.HardwareMailboxStatusAvailable; +} -/* - DAC960_ReleaseControllerLockIH releases exclusive access to Controller, - but is only called from the interrupt handler. -*/ +static inline +boolean DAC960_LP_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress) +{ + DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_LP_OutboundDoorBellRegisterOffset); + return OutboundDoorBellRegister.Read.MemoryMailboxStatusAvailable; +} static inline -void DAC960_ReleaseControllerLockIH(DAC960_Controller_T *Controller, - ProcessorFlags_T *ProcessorFlags) +void DAC960_LP_EnableInterrupts(void *ControllerBaseAddress) { - spin_unlock_irqrestore(&io_request_lock, *ProcessorFlags); + DAC960_LP_InterruptMaskRegister_T InterruptMaskRegister; + InterruptMaskRegister.All = 0xFF; + InterruptMaskRegister.Bits.DisableInterrupts = false; + writeb(InterruptMaskRegister.All, + ControllerBaseAddress + DAC960_LP_InterruptMaskRegisterOffset); +} + +static inline +void DAC960_LP_DisableInterrupts(void *ControllerBaseAddress) +{ + DAC960_LP_InterruptMaskRegister_T InterruptMaskRegister; + InterruptMaskRegister.All = 0xFF; + InterruptMaskRegister.Bits.DisableInterrupts = true; + writeb(InterruptMaskRegister.All, + ControllerBaseAddress + DAC960_LP_InterruptMaskRegisterOffset); +} + +static inline +boolean DAC960_LP_InterruptsEnabledP(void *ControllerBaseAddress) +{ + DAC960_LP_InterruptMaskRegister_T InterruptMaskRegister; + InterruptMaskRegister.All = + readb(ControllerBaseAddress + DAC960_LP_InterruptMaskRegisterOffset); + return !InterruptMaskRegister.Bits.DisableInterrupts; +} + +static inline +void DAC960_LP_WriteCommandMailbox(DAC960_V2_CommandMailbox_T + *MemoryCommandMailbox, + DAC960_V2_CommandMailbox_T + *CommandMailbox) +{ + memcpy(&MemoryCommandMailbox->Words[1], &CommandMailbox->Words[1], + sizeof(DAC960_V2_CommandMailbox_T) - sizeof(unsigned int)); + wmb(); + MemoryCommandMailbox->Words[0] = CommandMailbox->Words[0]; + mb(); +} + +static inline +void DAC960_LP_WriteHardwareMailbox(void *ControllerBaseAddress, + DAC960_V2_CommandMailbox_T *CommandMailbox) +{ + writel(Virtual_to_Bus(CommandMailbox), + ControllerBaseAddress + DAC960_LP_CommandMailboxBusAddressOffset); +} + +static inline DAC960_V2_CommandIdentifier_T +DAC960_LP_ReadCommandIdentifier(void *ControllerBaseAddress) +{ + return readw(ControllerBaseAddress + DAC960_LP_CommandStatusOffset); +} + +static inline DAC960_V2_CommandStatus_T +DAC960_LP_ReadCommandStatus(void *ControllerBaseAddress) +{ + return readw(ControllerBaseAddress + DAC960_LP_CommandStatusOffset + 2); +} + +static inline boolean +DAC960_LP_ReadErrorStatus(void *ControllerBaseAddress, + unsigned char *ErrorStatus, + unsigned char *Parameter0, + unsigned char *Parameter1) +{ + DAC960_LP_ErrorStatusRegister_T ErrorStatusRegister; + ErrorStatusRegister.All = + readb(ControllerBaseAddress + DAC960_LP_ErrorStatusRegisterOffset); + if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false; + ErrorStatusRegister.Bits.ErrorStatusPending = false; + *ErrorStatus = ErrorStatusRegister.All; + *Parameter0 = + readb(ControllerBaseAddress + DAC960_LP_CommandMailboxBusAddressOffset + 0); + *Parameter1 = + readb(ControllerBaseAddress + DAC960_LP_CommandMailboxBusAddressOffset + 1); + writeb(0xFF, ControllerBaseAddress + DAC960_LP_ErrorStatusRegisterOffset); + return true; } /* - Define the DAC960 V5 Controller Interface Register Offsets. + Define the DAC960 LA Series Controller Interface Register Offsets. */ -#define DAC960_V5_RegisterWindowSize 0x80 +#define DAC960_LA_RegisterWindowSize 0x80 typedef enum { - DAC960_V5_InboundDoorBellRegisterOffset = 0x60, - DAC960_V5_OutboundDoorBellRegisterOffset = 0x61, - DAC960_V5_InterruptMaskRegisterOffset = 0x34, - DAC960_V5_CommandOpcodeRegisterOffset = 0x50, - DAC960_V5_CommandIdentifierRegisterOffset = 0x51, - DAC960_V5_MailboxRegister2Offset = 0x52, - DAC960_V5_MailboxRegister3Offset = 0x53, - DAC960_V5_MailboxRegister4Offset = 0x54, - DAC960_V5_MailboxRegister5Offset = 0x55, - DAC960_V5_MailboxRegister6Offset = 0x56, - DAC960_V5_MailboxRegister7Offset = 0x57, - DAC960_V5_MailboxRegister8Offset = 0x58, - DAC960_V5_MailboxRegister9Offset = 0x59, - DAC960_V5_MailboxRegister10Offset = 0x5A, - DAC960_V5_MailboxRegister11Offset = 0x5B, - DAC960_V5_MailboxRegister12Offset = 0x5C, - DAC960_V5_StatusCommandIdentifierRegOffset = 0x5D, - DAC960_V5_StatusRegisterOffset = 0x5E, - DAC960_V5_ErrorStatusRegisterOffset = 0x63 + DAC960_LA_InboundDoorBellRegisterOffset = 0x60, + DAC960_LA_OutboundDoorBellRegisterOffset = 0x61, + DAC960_LA_InterruptMaskRegisterOffset = 0x34, + DAC960_LA_CommandOpcodeRegisterOffset = 0x50, + DAC960_LA_CommandIdentifierRegisterOffset = 0x51, + DAC960_LA_MailboxRegister2Offset = 0x52, + DAC960_LA_MailboxRegister3Offset = 0x53, + DAC960_LA_MailboxRegister4Offset = 0x54, + DAC960_LA_MailboxRegister5Offset = 0x55, + DAC960_LA_MailboxRegister6Offset = 0x56, + DAC960_LA_MailboxRegister7Offset = 0x57, + DAC960_LA_MailboxRegister8Offset = 0x58, + DAC960_LA_MailboxRegister9Offset = 0x59, + DAC960_LA_MailboxRegister10Offset = 0x5A, + DAC960_LA_MailboxRegister11Offset = 0x5B, + DAC960_LA_MailboxRegister12Offset = 0x5C, + DAC960_LA_StatusCommandIdentifierRegOffset = 0x5D, + DAC960_LA_StatusRegisterOffset = 0x5E, + DAC960_LA_ErrorStatusRegisterOffset = 0x63 } -DAC960_V5_RegisterOffsets_T; +DAC960_LA_RegisterOffsets_T; /* - Define the structure of the DAC960 V5 Inbound Door Bell Register. + Define the structure of the DAC960 LA Series Inbound Door Bell Register. */ -typedef union DAC960_V5_InboundDoorBellRegister +typedef union DAC960_LA_InboundDoorBellRegister { unsigned char All; struct { @@ -1421,14 +3178,14 @@ unsigned char :6; /* Bits 2-7 */ } Read; } -DAC960_V5_InboundDoorBellRegister_T; +DAC960_LA_InboundDoorBellRegister_T; /* - Define the structure of the DAC960 V5 Outbound Door Bell Register. + Define the structure of the DAC960 LA Series Outbound Door Bell Register. */ -typedef union DAC960_V5_OutboundDoorBellRegister +typedef union DAC960_LA_OutboundDoorBellRegister { unsigned char All; struct { @@ -1442,14 +3199,14 @@ unsigned char :6; /* Bits 2-7 */ } Read; } -DAC960_V5_OutboundDoorBellRegister_T; +DAC960_LA_OutboundDoorBellRegister_T; /* - Define the structure of the DAC960 V5 Interrupt Mask Register. + Define the structure of the DAC960 LA Series Interrupt Mask Register. */ -typedef union DAC960_V5_InterruptMaskRegister +typedef union DAC960_LA_InterruptMaskRegister { unsigned char All; struct { @@ -1458,14 +3215,14 @@ unsigned char :5; /* Bits 3-7 */ } Bits; } -DAC960_V5_InterruptMaskRegister_T; +DAC960_LA_InterruptMaskRegister_T; /* - Define the structure of the DAC960 V5 Error Status Register. + Define the structure of the DAC960 LA Series Error Status Register. */ -typedef union DAC960_V5_ErrorStatusRegister +typedef union DAC960_LA_ErrorStatusRegister { unsigned char All; struct { @@ -1474,288 +3231,294 @@ unsigned int :5; /* Bits 3-7 */ } Bits; } -DAC960_V5_ErrorStatusRegister_T; +DAC960_LA_ErrorStatusRegister_T; /* Define inline functions to provide an abstraction for reading and writing the - DAC960 V5 Controller Interface Registers. + DAC960 LA Series Controller Interface Registers. */ static inline -void DAC960_V5_HardwareMailboxNewCommand(void *ControllerBaseAddress) +void DAC960_LA_HardwareMailboxNewCommand(void *ControllerBaseAddress) { - DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.HardwareMailboxNewCommand = true; writeb(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_LA_InboundDoorBellRegisterOffset); } static inline -void DAC960_V5_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress) +void DAC960_LA_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress) { - DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.AcknowledgeHardwareMailboxStatus = true; writeb(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_LA_InboundDoorBellRegisterOffset); } static inline -void DAC960_V5_GenerateInterrupt(void *ControllerBaseAddress) +void DAC960_LA_GenerateInterrupt(void *ControllerBaseAddress) { - DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.GenerateInterrupt = true; writeb(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_LA_InboundDoorBellRegisterOffset); } static inline -void DAC960_V5_ControllerReset(void *ControllerBaseAddress) +void DAC960_LA_ControllerReset(void *ControllerBaseAddress) { - DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.ControllerReset = true; writeb(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_LA_InboundDoorBellRegisterOffset); } static inline -void DAC960_V5_MemoryMailboxNewCommand(void *ControllerBaseAddress) +void DAC960_LA_MemoryMailboxNewCommand(void *ControllerBaseAddress) { - DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.MemoryMailboxNewCommand = true; writeb(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_LA_InboundDoorBellRegisterOffset); } static inline -boolean DAC960_V5_HardwareMailboxFullP(void *ControllerBaseAddress) +boolean DAC960_LA_HardwareMailboxFullP(void *ControllerBaseAddress) { - DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = - readb(ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset); + readb(ControllerBaseAddress + DAC960_LA_InboundDoorBellRegisterOffset); return !InboundDoorBellRegister.Read.HardwareMailboxEmpty; } static inline -boolean DAC960_V5_InitializationInProgressP(void *ControllerBaseAddress) +boolean DAC960_LA_InitializationInProgressP(void *ControllerBaseAddress) { - DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = - readb(ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset); + readb(ControllerBaseAddress + DAC960_LA_InboundDoorBellRegisterOffset); return !InboundDoorBellRegister.Read.InitializationNotInProgress; } static inline -void DAC960_V5_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) +void DAC960_LA_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) { - DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister; + DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true; writeb(OutboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_LA_OutboundDoorBellRegisterOffset); } static inline -void DAC960_V5_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress) +void DAC960_LA_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress) { - DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister; + DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true; writeb(OutboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_LA_OutboundDoorBellRegisterOffset); } static inline -void DAC960_V5_AcknowledgeInterrupt(void *ControllerBaseAddress) +void DAC960_LA_AcknowledgeInterrupt(void *ControllerBaseAddress) { - DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister; + DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true; OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true; writeb(OutboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_LA_OutboundDoorBellRegisterOffset); } static inline -boolean DAC960_V5_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress) +boolean DAC960_LA_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress) { - DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister; + DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = - readb(ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset); + readb(ControllerBaseAddress + DAC960_LA_OutboundDoorBellRegisterOffset); return OutboundDoorBellRegister.Read.HardwareMailboxStatusAvailable; } static inline -boolean DAC960_V5_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress) +boolean DAC960_LA_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress) { - DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister; + DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = - readb(ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset); + readb(ControllerBaseAddress + DAC960_LA_OutboundDoorBellRegisterOffset); return OutboundDoorBellRegister.Read.MemoryMailboxStatusAvailable; } static inline -void DAC960_V5_EnableInterrupts(void *ControllerBaseAddress) +void DAC960_LA_EnableInterrupts(void *ControllerBaseAddress) { - DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister; + DAC960_LA_InterruptMaskRegister_T InterruptMaskRegister; InterruptMaskRegister.All = 0xFF; InterruptMaskRegister.Bits.DisableInterrupts = false; writeb(InterruptMaskRegister.All, - ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset); + ControllerBaseAddress + DAC960_LA_InterruptMaskRegisterOffset); } static inline -void DAC960_V5_DisableInterrupts(void *ControllerBaseAddress) +void DAC960_LA_DisableInterrupts(void *ControllerBaseAddress) { - DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister; + DAC960_LA_InterruptMaskRegister_T InterruptMaskRegister; InterruptMaskRegister.All = 0xFF; InterruptMaskRegister.Bits.DisableInterrupts = true; writeb(InterruptMaskRegister.All, - ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset); + ControllerBaseAddress + DAC960_LA_InterruptMaskRegisterOffset); } static inline -boolean DAC960_V5_InterruptsEnabledP(void *ControllerBaseAddress) +boolean DAC960_LA_InterruptsEnabledP(void *ControllerBaseAddress) { - DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister; + DAC960_LA_InterruptMaskRegister_T InterruptMaskRegister; InterruptMaskRegister.All = - readb(ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset); + readb(ControllerBaseAddress + DAC960_LA_InterruptMaskRegisterOffset); return !InterruptMaskRegister.Bits.DisableInterrupts; } static inline -void DAC960_V5_WriteCommandMailbox(DAC960_CommandMailbox_T *NextCommandMailbox, - DAC960_CommandMailbox_T *CommandMailbox) -{ - NextCommandMailbox->Words[1] = CommandMailbox->Words[1]; - NextCommandMailbox->Words[2] = CommandMailbox->Words[2]; - NextCommandMailbox->Words[3] = CommandMailbox->Words[3]; +void DAC960_LA_WriteCommandMailbox(DAC960_V1_CommandMailbox_T + *MemoryCommandMailbox, + DAC960_V1_CommandMailbox_T + *CommandMailbox) +{ + MemoryCommandMailbox->Words[1] = CommandMailbox->Words[1]; + MemoryCommandMailbox->Words[2] = CommandMailbox->Words[2]; + MemoryCommandMailbox->Words[3] = CommandMailbox->Words[3]; wmb(); - NextCommandMailbox->Words[0] = CommandMailbox->Words[0]; + MemoryCommandMailbox->Words[0] = CommandMailbox->Words[0]; mb(); } static inline -void DAC960_V5_WriteHardwareMailbox(void *ControllerBaseAddress, - DAC960_CommandMailbox_T *CommandMailbox) +void DAC960_LA_WriteHardwareMailbox(void *ControllerBaseAddress, + DAC960_V1_CommandMailbox_T *CommandMailbox) { writel(CommandMailbox->Words[0], - ControllerBaseAddress + DAC960_V5_CommandOpcodeRegisterOffset); + ControllerBaseAddress + DAC960_LA_CommandOpcodeRegisterOffset); writel(CommandMailbox->Words[1], - ControllerBaseAddress + DAC960_V5_MailboxRegister4Offset); + ControllerBaseAddress + DAC960_LA_MailboxRegister4Offset); writel(CommandMailbox->Words[2], - ControllerBaseAddress + DAC960_V5_MailboxRegister8Offset); + ControllerBaseAddress + DAC960_LA_MailboxRegister8Offset); writeb(CommandMailbox->Bytes[12], - ControllerBaseAddress + DAC960_V5_MailboxRegister12Offset); + ControllerBaseAddress + DAC960_LA_MailboxRegister12Offset); } -static inline DAC960_CommandIdentifier_T -DAC960_V5_ReadStatusCommandIdentifier(void *ControllerBaseAddress) +static inline DAC960_V1_CommandIdentifier_T +DAC960_LA_ReadStatusCommandIdentifier(void *ControllerBaseAddress) { return readb(ControllerBaseAddress - + DAC960_V5_StatusCommandIdentifierRegOffset); + + DAC960_LA_StatusCommandIdentifierRegOffset); } -static inline DAC960_CommandStatus_T -DAC960_V5_ReadStatusRegister(void *ControllerBaseAddress) +static inline DAC960_V1_CommandStatus_T +DAC960_LA_ReadStatusRegister(void *ControllerBaseAddress) { - return readw(ControllerBaseAddress + DAC960_V5_StatusRegisterOffset); + return readw(ControllerBaseAddress + DAC960_LA_StatusRegisterOffset); } static inline boolean -DAC960_V5_ReadErrorStatus(void *ControllerBaseAddress, +DAC960_LA_ReadErrorStatus(void *ControllerBaseAddress, unsigned char *ErrorStatus, unsigned char *Parameter0, unsigned char *Parameter1) { - DAC960_V5_ErrorStatusRegister_T ErrorStatusRegister; + DAC960_LA_ErrorStatusRegister_T ErrorStatusRegister; ErrorStatusRegister.All = - readb(ControllerBaseAddress + DAC960_V5_ErrorStatusRegisterOffset); + readb(ControllerBaseAddress + DAC960_LA_ErrorStatusRegisterOffset); if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false; ErrorStatusRegister.Bits.ErrorStatusPending = false; *ErrorStatus = ErrorStatusRegister.All; *Parameter0 = - readb(ControllerBaseAddress + DAC960_V5_CommandOpcodeRegisterOffset); + readb(ControllerBaseAddress + DAC960_LA_CommandOpcodeRegisterOffset); *Parameter1 = - readb(ControllerBaseAddress + DAC960_V5_CommandIdentifierRegisterOffset); - writeb(0xFF, ControllerBaseAddress + DAC960_V5_ErrorStatusRegisterOffset); + readb(ControllerBaseAddress + DAC960_LA_CommandIdentifierRegisterOffset); + writeb(0xFF, ControllerBaseAddress + DAC960_LA_ErrorStatusRegisterOffset); return true; } static inline -void DAC960_V5_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller) +void DAC960_LA_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller) { +#ifdef __i386__ void *ControllerBaseAddress = Controller->BaseAddress; writel(0x743C485E, - ControllerBaseAddress + DAC960_V5_CommandOpcodeRegisterOffset); - writel((unsigned long) Controller->FirstCommandMailbox, - ControllerBaseAddress + DAC960_V5_MailboxRegister4Offset); - writew(Controller->NextCommandMailbox - Controller->FirstCommandMailbox, - ControllerBaseAddress + DAC960_V5_MailboxRegister8Offset); - writew(Controller->NextStatusMailbox - Controller->FirstStatusMailbox, - ControllerBaseAddress + DAC960_V5_MailboxRegister10Offset); + ControllerBaseAddress + DAC960_LA_CommandOpcodeRegisterOffset); + writel((unsigned long) Controller->V1.FirstCommandMailbox, + ControllerBaseAddress + DAC960_LA_MailboxRegister4Offset); + writew(Controller->V1.NextCommandMailbox - Controller->V1.FirstCommandMailbox, + ControllerBaseAddress + DAC960_LA_MailboxRegister8Offset); + writew(Controller->V1.NextStatusMailbox - Controller->V1.FirstStatusMailbox, + ControllerBaseAddress + DAC960_LA_MailboxRegister10Offset); +#endif } static inline -void DAC960_V5_RestoreMemoryMailboxInfo(DAC960_Controller_T *Controller, +void DAC960_LA_RestoreMemoryMailboxInfo(DAC960_Controller_T *Controller, void **MemoryMailboxAddress, short *NextCommandMailboxIndex, short *NextStatusMailboxIndex) { +#ifdef __i386__ void *ControllerBaseAddress = Controller->BaseAddress; if (readl(ControllerBaseAddress - + DAC960_V5_CommandOpcodeRegisterOffset) != 0x743C485E) + + DAC960_LA_CommandOpcodeRegisterOffset) != 0x743C485E) return; *MemoryMailboxAddress = - (void *) readl(ControllerBaseAddress + DAC960_V5_MailboxRegister4Offset); + (void *) readl(ControllerBaseAddress + DAC960_LA_MailboxRegister4Offset); *NextCommandMailboxIndex = - readw(ControllerBaseAddress + DAC960_V5_MailboxRegister8Offset); + readw(ControllerBaseAddress + DAC960_LA_MailboxRegister8Offset); *NextStatusMailboxIndex = - readw(ControllerBaseAddress + DAC960_V5_MailboxRegister10Offset); + readw(ControllerBaseAddress + DAC960_LA_MailboxRegister10Offset); +#endif } /* - Define the DAC960 V4 Controller Interface Register Offsets. + Define the DAC960 PG Series Controller Interface Register Offsets. */ -#define DAC960_V4_RegisterWindowSize 0x2000 +#define DAC960_PG_RegisterWindowSize 0x2000 typedef enum { - DAC960_V4_InboundDoorBellRegisterOffset = 0x0020, - DAC960_V4_OutboundDoorBellRegisterOffset = 0x002C, - DAC960_V4_InterruptMaskRegisterOffset = 0x0034, - DAC960_V4_CommandOpcodeRegisterOffset = 0x1000, - DAC960_V4_CommandIdentifierRegisterOffset = 0x1001, - DAC960_V4_MailboxRegister2Offset = 0x1002, - DAC960_V4_MailboxRegister3Offset = 0x1003, - DAC960_V4_MailboxRegister4Offset = 0x1004, - DAC960_V4_MailboxRegister5Offset = 0x1005, - DAC960_V4_MailboxRegister6Offset = 0x1006, - DAC960_V4_MailboxRegister7Offset = 0x1007, - DAC960_V4_MailboxRegister8Offset = 0x1008, - DAC960_V4_MailboxRegister9Offset = 0x1009, - DAC960_V4_MailboxRegister10Offset = 0x100A, - DAC960_V4_MailboxRegister11Offset = 0x100B, - DAC960_V4_MailboxRegister12Offset = 0x100C, - DAC960_V4_StatusCommandIdentifierRegOffset = 0x1018, - DAC960_V4_StatusRegisterOffset = 0x101A, - DAC960_V4_ErrorStatusRegisterOffset = 0x103F + DAC960_PG_InboundDoorBellRegisterOffset = 0x0020, + DAC960_PG_OutboundDoorBellRegisterOffset = 0x002C, + DAC960_PG_InterruptMaskRegisterOffset = 0x0034, + DAC960_PG_CommandOpcodeRegisterOffset = 0x1000, + DAC960_PG_CommandIdentifierRegisterOffset = 0x1001, + DAC960_PG_MailboxRegister2Offset = 0x1002, + DAC960_PG_MailboxRegister3Offset = 0x1003, + DAC960_PG_MailboxRegister4Offset = 0x1004, + DAC960_PG_MailboxRegister5Offset = 0x1005, + DAC960_PG_MailboxRegister6Offset = 0x1006, + DAC960_PG_MailboxRegister7Offset = 0x1007, + DAC960_PG_MailboxRegister8Offset = 0x1008, + DAC960_PG_MailboxRegister9Offset = 0x1009, + DAC960_PG_MailboxRegister10Offset = 0x100A, + DAC960_PG_MailboxRegister11Offset = 0x100B, + DAC960_PG_MailboxRegister12Offset = 0x100C, + DAC960_PG_StatusCommandIdentifierRegOffset = 0x1018, + DAC960_PG_StatusRegisterOffset = 0x101A, + DAC960_PG_ErrorStatusRegisterOffset = 0x103F } -DAC960_V4_RegisterOffsets_T; +DAC960_PG_RegisterOffsets_T; /* - Define the structure of the DAC960 V4 Inbound Door Bell Register. + Define the structure of the DAC960 PG Series Inbound Door Bell Register. */ -typedef union DAC960_V4_InboundDoorBellRegister +typedef union DAC960_PG_InboundDoorBellRegister { unsigned int All; struct { @@ -1772,14 +3535,14 @@ unsigned int :30; /* Bits 2-31 */ } Read; } -DAC960_V4_InboundDoorBellRegister_T; +DAC960_PG_InboundDoorBellRegister_T; /* - Define the structure of the DAC960 V4 Outbound Door Bell Register. + Define the structure of the DAC960 PG Series Outbound Door Bell Register. */ -typedef union DAC960_V4_OutboundDoorBellRegister +typedef union DAC960_PG_OutboundDoorBellRegister { unsigned int All; struct { @@ -1793,14 +3556,14 @@ unsigned int :30; /* Bits 2-31 */ } Read; } -DAC960_V4_OutboundDoorBellRegister_T; +DAC960_PG_OutboundDoorBellRegister_T; /* - Define the structure of the DAC960 V4 Interrupt Mask Register. + Define the structure of the DAC960 PG Series Interrupt Mask Register. */ -typedef union DAC960_V4_InterruptMaskRegister +typedef union DAC960_PG_InterruptMaskRegister { unsigned int All; struct { @@ -1810,14 +3573,14 @@ unsigned int Reserved0:24; /* Bits 8-31 */ } Bits; } -DAC960_V4_InterruptMaskRegister_T; +DAC960_PG_InterruptMaskRegister_T; /* - Define the structure of the DAC960 V4 Error Status Register. + Define the structure of the DAC960 PG Series Error Status Register. */ -typedef union DAC960_V4_ErrorStatusRegister +typedef union DAC960_PG_ErrorStatusRegister { unsigned char All; struct { @@ -1826,292 +3589,298 @@ unsigned int :5; /* Bits 3-7 */ } Bits; } -DAC960_V4_ErrorStatusRegister_T; +DAC960_PG_ErrorStatusRegister_T; /* Define inline functions to provide an abstraction for reading and writing the - DAC960 V4 Controller Interface Registers. + DAC960 PG Series Controller Interface Registers. */ static inline -void DAC960_V4_HardwareMailboxNewCommand(void *ControllerBaseAddress) +void DAC960_PG_HardwareMailboxNewCommand(void *ControllerBaseAddress) { - DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.HardwareMailboxNewCommand = true; writel(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PG_InboundDoorBellRegisterOffset); } static inline -void DAC960_V4_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress) +void DAC960_PG_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress) { - DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.AcknowledgeHardwareMailboxStatus = true; writel(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PG_InboundDoorBellRegisterOffset); } static inline -void DAC960_V4_GenerateInterrupt(void *ControllerBaseAddress) +void DAC960_PG_GenerateInterrupt(void *ControllerBaseAddress) { - DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.GenerateInterrupt = true; writel(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PG_InboundDoorBellRegisterOffset); } static inline -void DAC960_V4_ControllerReset(void *ControllerBaseAddress) +void DAC960_PG_ControllerReset(void *ControllerBaseAddress) { - DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.ControllerReset = true; writel(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PG_InboundDoorBellRegisterOffset); } static inline -void DAC960_V4_MemoryMailboxNewCommand(void *ControllerBaseAddress) +void DAC960_PG_MemoryMailboxNewCommand(void *ControllerBaseAddress) { - DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.MemoryMailboxNewCommand = true; writel(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PG_InboundDoorBellRegisterOffset); } static inline -boolean DAC960_V4_HardwareMailboxFullP(void *ControllerBaseAddress) +boolean DAC960_PG_HardwareMailboxFullP(void *ControllerBaseAddress) { - DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = - readl(ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset); + readl(ControllerBaseAddress + DAC960_PG_InboundDoorBellRegisterOffset); return InboundDoorBellRegister.Read.HardwareMailboxFull; } static inline -boolean DAC960_V4_InitializationInProgressP(void *ControllerBaseAddress) +boolean DAC960_PG_InitializationInProgressP(void *ControllerBaseAddress) { - DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = - readl(ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset); + readl(ControllerBaseAddress + DAC960_PG_InboundDoorBellRegisterOffset); return InboundDoorBellRegister.Read.InitializationInProgress; } static inline -void DAC960_V4_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) +void DAC960_PG_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) { - DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister; + DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true; writel(OutboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PG_OutboundDoorBellRegisterOffset); } static inline -void DAC960_V4_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress) +void DAC960_PG_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress) { - DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister; + DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true; writel(OutboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PG_OutboundDoorBellRegisterOffset); } static inline -void DAC960_V4_AcknowledgeInterrupt(void *ControllerBaseAddress) +void DAC960_PG_AcknowledgeInterrupt(void *ControllerBaseAddress) { - DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister; + DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true; OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true; writel(OutboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PG_OutboundDoorBellRegisterOffset); } static inline -boolean DAC960_V4_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress) +boolean DAC960_PG_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress) { - DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister; + DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = - readl(ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset); + readl(ControllerBaseAddress + DAC960_PG_OutboundDoorBellRegisterOffset); return OutboundDoorBellRegister.Read.HardwareMailboxStatusAvailable; } static inline -boolean DAC960_V4_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress) +boolean DAC960_PG_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress) { - DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister; + DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = - readl(ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset); + readl(ControllerBaseAddress + DAC960_PG_OutboundDoorBellRegisterOffset); return OutboundDoorBellRegister.Read.MemoryMailboxStatusAvailable; } static inline -void DAC960_V4_EnableInterrupts(void *ControllerBaseAddress) +void DAC960_PG_EnableInterrupts(void *ControllerBaseAddress) { - DAC960_V4_InterruptMaskRegister_T InterruptMaskRegister; + DAC960_PG_InterruptMaskRegister_T InterruptMaskRegister; InterruptMaskRegister.All = 0; InterruptMaskRegister.Bits.MessageUnitInterruptMask1 = 0x3; InterruptMaskRegister.Bits.DisableInterrupts = false; InterruptMaskRegister.Bits.MessageUnitInterruptMask2 = 0x1F; writel(InterruptMaskRegister.All, - ControllerBaseAddress + DAC960_V4_InterruptMaskRegisterOffset); + ControllerBaseAddress + DAC960_PG_InterruptMaskRegisterOffset); } static inline -void DAC960_V4_DisableInterrupts(void *ControllerBaseAddress) +void DAC960_PG_DisableInterrupts(void *ControllerBaseAddress) { - DAC960_V4_InterruptMaskRegister_T InterruptMaskRegister; + DAC960_PG_InterruptMaskRegister_T InterruptMaskRegister; InterruptMaskRegister.All = 0; InterruptMaskRegister.Bits.MessageUnitInterruptMask1 = 0x3; InterruptMaskRegister.Bits.DisableInterrupts = true; InterruptMaskRegister.Bits.MessageUnitInterruptMask2 = 0x1F; writel(InterruptMaskRegister.All, - ControllerBaseAddress + DAC960_V4_InterruptMaskRegisterOffset); + ControllerBaseAddress + DAC960_PG_InterruptMaskRegisterOffset); } static inline -boolean DAC960_V4_InterruptsEnabledP(void *ControllerBaseAddress) +boolean DAC960_PG_InterruptsEnabledP(void *ControllerBaseAddress) { - DAC960_V4_InterruptMaskRegister_T InterruptMaskRegister; + DAC960_PG_InterruptMaskRegister_T InterruptMaskRegister; InterruptMaskRegister.All = - readl(ControllerBaseAddress + DAC960_V4_InterruptMaskRegisterOffset); + readl(ControllerBaseAddress + DAC960_PG_InterruptMaskRegisterOffset); return !InterruptMaskRegister.Bits.DisableInterrupts; } static inline -void DAC960_V4_WriteCommandMailbox(DAC960_CommandMailbox_T *NextCommandMailbox, - DAC960_CommandMailbox_T *CommandMailbox) -{ - NextCommandMailbox->Words[1] = CommandMailbox->Words[1]; - NextCommandMailbox->Words[2] = CommandMailbox->Words[2]; - NextCommandMailbox->Words[3] = CommandMailbox->Words[3]; +void DAC960_PG_WriteCommandMailbox(DAC960_V1_CommandMailbox_T + *MemoryCommandMailbox, + DAC960_V1_CommandMailbox_T + *CommandMailbox) +{ + MemoryCommandMailbox->Words[1] = CommandMailbox->Words[1]; + MemoryCommandMailbox->Words[2] = CommandMailbox->Words[2]; + MemoryCommandMailbox->Words[3] = CommandMailbox->Words[3]; wmb(); - NextCommandMailbox->Words[0] = CommandMailbox->Words[0]; + MemoryCommandMailbox->Words[0] = CommandMailbox->Words[0]; mb(); } static inline -void DAC960_V4_WriteHardwareMailbox(void *ControllerBaseAddress, - DAC960_CommandMailbox_T *CommandMailbox) +void DAC960_PG_WriteHardwareMailbox(void *ControllerBaseAddress, + DAC960_V1_CommandMailbox_T *CommandMailbox) { writel(CommandMailbox->Words[0], - ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset); + ControllerBaseAddress + DAC960_PG_CommandOpcodeRegisterOffset); writel(CommandMailbox->Words[1], - ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset); + ControllerBaseAddress + DAC960_PG_MailboxRegister4Offset); writel(CommandMailbox->Words[2], - ControllerBaseAddress + DAC960_V4_MailboxRegister8Offset); + ControllerBaseAddress + DAC960_PG_MailboxRegister8Offset); writeb(CommandMailbox->Bytes[12], - ControllerBaseAddress + DAC960_V4_MailboxRegister12Offset); + ControllerBaseAddress + DAC960_PG_MailboxRegister12Offset); } -static inline DAC960_CommandIdentifier_T -DAC960_V4_ReadStatusCommandIdentifier(void *ControllerBaseAddress) +static inline DAC960_V1_CommandIdentifier_T +DAC960_PG_ReadStatusCommandIdentifier(void *ControllerBaseAddress) { return readb(ControllerBaseAddress - + DAC960_V4_StatusCommandIdentifierRegOffset); + + DAC960_PG_StatusCommandIdentifierRegOffset); } -static inline DAC960_CommandStatus_T -DAC960_V4_ReadStatusRegister(void *ControllerBaseAddress) +static inline DAC960_V1_CommandStatus_T +DAC960_PG_ReadStatusRegister(void *ControllerBaseAddress) { - return readw(ControllerBaseAddress + DAC960_V4_StatusRegisterOffset); + return readw(ControllerBaseAddress + DAC960_PG_StatusRegisterOffset); } static inline boolean -DAC960_V4_ReadErrorStatus(void *ControllerBaseAddress, +DAC960_PG_ReadErrorStatus(void *ControllerBaseAddress, unsigned char *ErrorStatus, unsigned char *Parameter0, unsigned char *Parameter1) { - DAC960_V4_ErrorStatusRegister_T ErrorStatusRegister; + DAC960_PG_ErrorStatusRegister_T ErrorStatusRegister; ErrorStatusRegister.All = - readb(ControllerBaseAddress + DAC960_V4_ErrorStatusRegisterOffset); + readb(ControllerBaseAddress + DAC960_PG_ErrorStatusRegisterOffset); if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false; ErrorStatusRegister.Bits.ErrorStatusPending = false; *ErrorStatus = ErrorStatusRegister.All; *Parameter0 = - readb(ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset); + readb(ControllerBaseAddress + DAC960_PG_CommandOpcodeRegisterOffset); *Parameter1 = - readb(ControllerBaseAddress + DAC960_V4_CommandIdentifierRegisterOffset); - writeb(0, ControllerBaseAddress + DAC960_V4_ErrorStatusRegisterOffset); + readb(ControllerBaseAddress + DAC960_PG_CommandIdentifierRegisterOffset); + writeb(0, ControllerBaseAddress + DAC960_PG_ErrorStatusRegisterOffset); return true; } static inline -void DAC960_V4_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller) +void DAC960_PG_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller) { +#ifdef __i386__ void *ControllerBaseAddress = Controller->BaseAddress; writel(0x743C485E, - ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset); - writel((unsigned long) Controller->FirstCommandMailbox, - ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset); - writew(Controller->NextCommandMailbox - Controller->FirstCommandMailbox, - ControllerBaseAddress + DAC960_V4_MailboxRegister8Offset); - writew(Controller->NextStatusMailbox - Controller->FirstStatusMailbox, - ControllerBaseAddress + DAC960_V4_MailboxRegister10Offset); + ControllerBaseAddress + DAC960_PG_CommandOpcodeRegisterOffset); + writel((unsigned long) Controller->V1.FirstCommandMailbox, + ControllerBaseAddress + DAC960_PG_MailboxRegister4Offset); + writew(Controller->V1.NextCommandMailbox - Controller->V1.FirstCommandMailbox, + ControllerBaseAddress + DAC960_PG_MailboxRegister8Offset); + writew(Controller->V1.NextStatusMailbox - Controller->V1.FirstStatusMailbox, + ControllerBaseAddress + DAC960_PG_MailboxRegister10Offset); +#endif } static inline -void DAC960_V4_RestoreMemoryMailboxInfo(DAC960_Controller_T *Controller, +void DAC960_PG_RestoreMemoryMailboxInfo(DAC960_Controller_T *Controller, void **MemoryMailboxAddress, short *NextCommandMailboxIndex, short *NextStatusMailboxIndex) { +#ifdef __i386__ void *ControllerBaseAddress = Controller->BaseAddress; if (readl(ControllerBaseAddress - + DAC960_V4_CommandOpcodeRegisterOffset) != 0x743C485E) + + DAC960_PG_CommandOpcodeRegisterOffset) != 0x743C485E) return; *MemoryMailboxAddress = - (void *) readl(ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset); + (void *) readl(ControllerBaseAddress + DAC960_PG_MailboxRegister4Offset); *NextCommandMailboxIndex = - readw(ControllerBaseAddress + DAC960_V4_MailboxRegister8Offset); + readw(ControllerBaseAddress + DAC960_PG_MailboxRegister8Offset); *NextStatusMailboxIndex = - readw(ControllerBaseAddress + DAC960_V4_MailboxRegister10Offset); + readw(ControllerBaseAddress + DAC960_PG_MailboxRegister10Offset); +#endif } /* - Define the DAC960 V3 Controller Interface Register Offsets. + Define the DAC960 PD Series Controller Interface Register Offsets. */ -#define DAC960_V3_RegisterWindowSize 0x80 +#define DAC960_PD_RegisterWindowSize 0x80 typedef enum { - DAC960_V3_CommandOpcodeRegisterOffset = 0x00, - DAC960_V3_CommandIdentifierRegisterOffset = 0x01, - DAC960_V3_MailboxRegister2Offset = 0x02, - DAC960_V3_MailboxRegister3Offset = 0x03, - DAC960_V3_MailboxRegister4Offset = 0x04, - DAC960_V3_MailboxRegister5Offset = 0x05, - DAC960_V3_MailboxRegister6Offset = 0x06, - DAC960_V3_MailboxRegister7Offset = 0x07, - DAC960_V3_MailboxRegister8Offset = 0x08, - DAC960_V3_MailboxRegister9Offset = 0x09, - DAC960_V3_MailboxRegister10Offset = 0x0A, - DAC960_V3_MailboxRegister11Offset = 0x0B, - DAC960_V3_MailboxRegister12Offset = 0x0C, - DAC960_V3_StatusCommandIdentifierRegOffset = 0x0D, - DAC960_V3_StatusRegisterOffset = 0x0E, - DAC960_V3_ErrorStatusRegisterOffset = 0x3F, - DAC960_V3_InboundDoorBellRegisterOffset = 0x40, - DAC960_V3_OutboundDoorBellRegisterOffset = 0x41, - DAC960_V3_InterruptEnableRegisterOffset = 0x43 + DAC960_PD_CommandOpcodeRegisterOffset = 0x00, + DAC960_PD_CommandIdentifierRegisterOffset = 0x01, + DAC960_PD_MailboxRegister2Offset = 0x02, + DAC960_PD_MailboxRegister3Offset = 0x03, + DAC960_PD_MailboxRegister4Offset = 0x04, + DAC960_PD_MailboxRegister5Offset = 0x05, + DAC960_PD_MailboxRegister6Offset = 0x06, + DAC960_PD_MailboxRegister7Offset = 0x07, + DAC960_PD_MailboxRegister8Offset = 0x08, + DAC960_PD_MailboxRegister9Offset = 0x09, + DAC960_PD_MailboxRegister10Offset = 0x0A, + DAC960_PD_MailboxRegister11Offset = 0x0B, + DAC960_PD_MailboxRegister12Offset = 0x0C, + DAC960_PD_StatusCommandIdentifierRegOffset = 0x0D, + DAC960_PD_StatusRegisterOffset = 0x0E, + DAC960_PD_ErrorStatusRegisterOffset = 0x3F, + DAC960_PD_InboundDoorBellRegisterOffset = 0x40, + DAC960_PD_OutboundDoorBellRegisterOffset = 0x41, + DAC960_PD_InterruptEnableRegisterOffset = 0x43 } -DAC960_V3_RegisterOffsets_T; +DAC960_PD_RegisterOffsets_T; /* - Define the structure of the DAC960 V3 Inbound Door Bell Register. + Define the structure of the DAC960 PD Series Inbound Door Bell Register. */ -typedef union DAC960_V3_InboundDoorBellRegister +typedef union DAC960_PD_InboundDoorBellRegister { unsigned char All; struct { @@ -2127,14 +3896,14 @@ unsigned char :6; /* Bits 2-7 */ } Read; } -DAC960_V3_InboundDoorBellRegister_T; +DAC960_PD_InboundDoorBellRegister_T; /* - Define the structure of the DAC960 V3 Outbound Door Bell Register. + Define the structure of the DAC960 PD Series Outbound Door Bell Register. */ -typedef union DAC960_V3_OutboundDoorBellRegister +typedef union DAC960_PD_OutboundDoorBellRegister { unsigned char All; struct { @@ -2146,14 +3915,14 @@ unsigned char :7; /* Bits 1-7 */ } Read; } -DAC960_V3_OutboundDoorBellRegister_T; +DAC960_PD_OutboundDoorBellRegister_T; /* - Define the structure of the DAC960 V3 Interrupt Enable Register. + Define the structure of the DAC960 PD Series Interrupt Enable Register. */ -typedef union DAC960_V3_InterruptEnableRegister +typedef union DAC960_PD_InterruptEnableRegister { unsigned char All; struct { @@ -2161,14 +3930,14 @@ unsigned char :7; /* Bits 1-7 */ } Bits; } -DAC960_V3_InterruptEnableRegister_T; +DAC960_PD_InterruptEnableRegister_T; /* - Define the structure of the DAC960 V3 Error Status Register. + Define the structure of the DAC960 PD Series Error Status Register. */ -typedef union DAC960_V3_ErrorStatusRegister +typedef union DAC960_PD_ErrorStatusRegister { unsigned char All; struct { @@ -2177,204 +3946,190 @@ unsigned int :5; /* Bits 3-7 */ } Bits; } -DAC960_V3_ErrorStatusRegister_T; +DAC960_PD_ErrorStatusRegister_T; /* Define inline functions to provide an abstraction for reading and writing the - DAC960 V3 Controller Interface Registers. + DAC960 PD Series Controller Interface Registers. */ static inline -void DAC960_V3_NewCommand(void *ControllerBaseAddress) +void DAC960_PD_NewCommand(void *ControllerBaseAddress) { - DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.NewCommand = true; writeb(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PD_InboundDoorBellRegisterOffset); } static inline -void DAC960_V3_AcknowledgeStatus(void *ControllerBaseAddress) +void DAC960_PD_AcknowledgeStatus(void *ControllerBaseAddress) { - DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.AcknowledgeStatus = true; writeb(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PD_InboundDoorBellRegisterOffset); } static inline -void DAC960_V3_GenerateInterrupt(void *ControllerBaseAddress) +void DAC960_PD_GenerateInterrupt(void *ControllerBaseAddress) { - DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.GenerateInterrupt = true; writeb(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PD_InboundDoorBellRegisterOffset); } static inline -void DAC960_V3_ControllerReset(void *ControllerBaseAddress) +void DAC960_PD_ControllerReset(void *ControllerBaseAddress) { - DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.ControllerReset = true; writeb(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PD_InboundDoorBellRegisterOffset); } static inline -boolean DAC960_V3_MailboxFullP(void *ControllerBaseAddress) +boolean DAC960_PD_MailboxFullP(void *ControllerBaseAddress) { - DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = - readb(ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset); + readb(ControllerBaseAddress + DAC960_PD_InboundDoorBellRegisterOffset); return InboundDoorBellRegister.Read.MailboxFull; } static inline -boolean DAC960_V3_InitializationInProgressP(void *ControllerBaseAddress) +boolean DAC960_PD_InitializationInProgressP(void *ControllerBaseAddress) { - DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = - readb(ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset); + readb(ControllerBaseAddress + DAC960_PD_InboundDoorBellRegisterOffset); return InboundDoorBellRegister.Read.InitializationInProgress; } static inline -void DAC960_V3_AcknowledgeInterrupt(void *ControllerBaseAddress) +void DAC960_PD_AcknowledgeInterrupt(void *ControllerBaseAddress) { - DAC960_V3_OutboundDoorBellRegister_T OutboundDoorBellRegister; + DAC960_PD_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; OutboundDoorBellRegister.Write.AcknowledgeInterrupt = true; writeb(OutboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V3_OutboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PD_OutboundDoorBellRegisterOffset); } static inline -boolean DAC960_V3_StatusAvailableP(void *ControllerBaseAddress) +boolean DAC960_PD_StatusAvailableP(void *ControllerBaseAddress) { - DAC960_V3_OutboundDoorBellRegister_T OutboundDoorBellRegister; + DAC960_PD_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = - readb(ControllerBaseAddress + DAC960_V3_OutboundDoorBellRegisterOffset); + readb(ControllerBaseAddress + DAC960_PD_OutboundDoorBellRegisterOffset); return OutboundDoorBellRegister.Read.StatusAvailable; } static inline -void DAC960_V3_EnableInterrupts(void *ControllerBaseAddress) +void DAC960_PD_EnableInterrupts(void *ControllerBaseAddress) { - DAC960_V3_InterruptEnableRegister_T InterruptEnableRegister; + DAC960_PD_InterruptEnableRegister_T InterruptEnableRegister; InterruptEnableRegister.All = 0; InterruptEnableRegister.Bits.EnableInterrupts = true; writeb(InterruptEnableRegister.All, - ControllerBaseAddress + DAC960_V3_InterruptEnableRegisterOffset); + ControllerBaseAddress + DAC960_PD_InterruptEnableRegisterOffset); } static inline -void DAC960_V3_DisableInterrupts(void *ControllerBaseAddress) +void DAC960_PD_DisableInterrupts(void *ControllerBaseAddress) { - DAC960_V3_InterruptEnableRegister_T InterruptEnableRegister; + DAC960_PD_InterruptEnableRegister_T InterruptEnableRegister; InterruptEnableRegister.All = 0; InterruptEnableRegister.Bits.EnableInterrupts = false; writeb(InterruptEnableRegister.All, - ControllerBaseAddress + DAC960_V3_InterruptEnableRegisterOffset); + ControllerBaseAddress + DAC960_PD_InterruptEnableRegisterOffset); } static inline -boolean DAC960_V3_InterruptsEnabledP(void *ControllerBaseAddress) +boolean DAC960_PD_InterruptsEnabledP(void *ControllerBaseAddress) { - DAC960_V3_InterruptEnableRegister_T InterruptEnableRegister; + DAC960_PD_InterruptEnableRegister_T InterruptEnableRegister; InterruptEnableRegister.All = - readb(ControllerBaseAddress + DAC960_V3_InterruptEnableRegisterOffset); + readb(ControllerBaseAddress + DAC960_PD_InterruptEnableRegisterOffset); return InterruptEnableRegister.Bits.EnableInterrupts; } static inline -void DAC960_V3_WriteCommandMailbox(void *ControllerBaseAddress, - DAC960_CommandMailbox_T *CommandMailbox) +void DAC960_PD_WriteCommandMailbox(void *ControllerBaseAddress, + DAC960_V1_CommandMailbox_T *CommandMailbox) { writel(CommandMailbox->Words[0], - ControllerBaseAddress + DAC960_V3_CommandOpcodeRegisterOffset); + ControllerBaseAddress + DAC960_PD_CommandOpcodeRegisterOffset); writel(CommandMailbox->Words[1], - ControllerBaseAddress + DAC960_V3_MailboxRegister4Offset); + ControllerBaseAddress + DAC960_PD_MailboxRegister4Offset); writel(CommandMailbox->Words[2], - ControllerBaseAddress + DAC960_V3_MailboxRegister8Offset); + ControllerBaseAddress + DAC960_PD_MailboxRegister8Offset); writeb(CommandMailbox->Bytes[12], - ControllerBaseAddress + DAC960_V3_MailboxRegister12Offset); + ControllerBaseAddress + DAC960_PD_MailboxRegister12Offset); } -static inline DAC960_CommandIdentifier_T -DAC960_V3_ReadStatusCommandIdentifier(void *ControllerBaseAddress) +static inline DAC960_V1_CommandIdentifier_T +DAC960_PD_ReadStatusCommandIdentifier(void *ControllerBaseAddress) { return readb(ControllerBaseAddress - + DAC960_V3_StatusCommandIdentifierRegOffset); + + DAC960_PD_StatusCommandIdentifierRegOffset); } -static inline DAC960_CommandStatus_T -DAC960_V3_ReadStatusRegister(void *ControllerBaseAddress) +static inline DAC960_V1_CommandStatus_T +DAC960_PD_ReadStatusRegister(void *ControllerBaseAddress) { - return readw(ControllerBaseAddress + DAC960_V3_StatusRegisterOffset); + return readw(ControllerBaseAddress + DAC960_PD_StatusRegisterOffset); } static inline boolean -DAC960_V3_ReadErrorStatus(void *ControllerBaseAddress, +DAC960_PD_ReadErrorStatus(void *ControllerBaseAddress, unsigned char *ErrorStatus, unsigned char *Parameter0, unsigned char *Parameter1) { - DAC960_V3_ErrorStatusRegister_T ErrorStatusRegister; + DAC960_PD_ErrorStatusRegister_T ErrorStatusRegister; ErrorStatusRegister.All = - readb(ControllerBaseAddress + DAC960_V3_ErrorStatusRegisterOffset); + readb(ControllerBaseAddress + DAC960_PD_ErrorStatusRegisterOffset); if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false; ErrorStatusRegister.Bits.ErrorStatusPending = false; *ErrorStatus = ErrorStatusRegister.All; *Parameter0 = - readb(ControllerBaseAddress + DAC960_V3_CommandOpcodeRegisterOffset); + readb(ControllerBaseAddress + DAC960_PD_CommandOpcodeRegisterOffset); *Parameter1 = - readb(ControllerBaseAddress + DAC960_V3_CommandIdentifierRegisterOffset); - writeb(0, ControllerBaseAddress + DAC960_V3_ErrorStatusRegisterOffset); + readb(ControllerBaseAddress + DAC960_PD_CommandIdentifierRegisterOffset); + writeb(0, ControllerBaseAddress + DAC960_PD_ErrorStatusRegisterOffset); return true; } /* - Define compatibility macros between Linux 2.0 and Linux 2.1. -*/ - -#if LINUX_VERSION_CODE < 0x20100 - -#define MODULE_PARM(Variable, Type) -#define ioremap_nocache(Offset, Size) vremap(Offset, Size) -#define iounmap(Address) vfree(Address) - -#endif - - -/* Define prototypes for the forward referenced DAC960 Driver Internal Functions. */ static void DAC960_FinalizeController(DAC960_Controller_T *); static int DAC960_Finalize(NotifierBlock_T *, unsigned long, void *); -static void DAC960_RequestFunction0(request_queue_t *); -static void DAC960_RequestFunction1(request_queue_t *); -static void DAC960_RequestFunction2(request_queue_t *); -static void DAC960_RequestFunction3(request_queue_t *); -static void DAC960_RequestFunction4(request_queue_t *); -static void DAC960_RequestFunction5(request_queue_t *); -static void DAC960_RequestFunction6(request_queue_t *); -static void DAC960_RequestFunction7(request_queue_t *); -static void DAC960_InterruptHandler(int, void *, Registers_T *); -static void DAC960_QueueMonitoringCommand(DAC960_Command_T *); +static void DAC960_V1_QueueReadWriteCommand(DAC960_Command_T *); +static void DAC960_V2_QueueReadWriteCommand(DAC960_Command_T *); +static void DAC960_RequestFunction(RequestQueue_T *); +static void DAC960_BA_InterruptHandler(int, void *, Registers_T *); +static void DAC960_LP_InterruptHandler(int, void *, Registers_T *); +static void DAC960_LA_InterruptHandler(int, void *, Registers_T *); +static void DAC960_PG_InterruptHandler(int, void *, Registers_T *); +static void DAC960_PD_InterruptHandler(int, void *, Registers_T *); +static void DAC960_V1_QueueMonitoringCommand(DAC960_Command_T *); +static void DAC960_V2_QueueMonitoringCommand(DAC960_Command_T *); static void DAC960_MonitoringTimerFunction(unsigned long); static int DAC960_Open(Inode_T *, File_T *); static int DAC960_Release(Inode_T *, File_T *); static int DAC960_IOCTL(Inode_T *, File_T *, unsigned int, unsigned long); static int DAC960_UserIOCTL(Inode_T *, File_T *, unsigned int, unsigned long); -static void DAC960_InitializeGenericDiskInfo(GenericDiskInfo_T *); -static void DAC960_Message(DAC960_MessageLevel_T, char *, +static void DAC960_Message(DAC960_MessageLevel_T, unsigned char *, DAC960_Controller_T *, ...); static void DAC960_CreateProcEntries(void); static void DAC960_DestroyProcEntries(void); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/block/Makefile linux/drivers/block/Makefile --- v2.4.0-test5/linux/drivers/block/Makefile Thu Jul 27 17:38:00 2000 +++ linux/drivers/block/Makefile Sun Aug 6 11:23:40 2000 @@ -13,8 +13,6 @@ ALL_SUB_DIRS := $(SUB_DIRS) paride O_TARGET := block.o -MOD_LIST_NAME := BLOCK_MODULES - export-objs := ll_rw_blk.o blkpg.o loop.o DAC960.o md.o xor.o list-multi := lvm-mod.o diff -u --recursive --new-file v2.4.0-test5/linux/drivers/block/floppy.c linux/drivers/block/floppy.c --- v2.4.0-test5/linux/drivers/block/floppy.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/block/floppy.c Sun Aug 6 22:00:41 2000 @@ -3429,9 +3429,6 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long param) { -#define IOCTL_MODE_BIT 8 -#define OPEN_WRITE_BIT 16 -#define IOCTL_ALLOWED (filp && (filp->f_mode & IOCTL_MODE_BIT)) #define OUT(c,x) case c: outparam = (const char *) (x); break #define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0 @@ -3499,7 +3496,7 @@ return -EINVAL; /* permission checks */ - if (((cmd & 0x40) && !IOCTL_ALLOWED) || + if (((cmd & 0x40) && !(filp->f_mode & 2)) || ((cmd & 0x80) && !suser())) return -EPERM; @@ -3620,7 +3617,6 @@ return fd_copyout((void *)param, outparam, size); else return 0; -#undef IOCTL_ALLOWED #undef OUT #undef IN } @@ -3772,12 +3768,6 @@ buffer_track = -1; invalidate_buffers(MKDEV(FLOPPY_MAJOR,old_dev)); } - - /* Allow ioctls if we have write-permissions even if read-only open */ - if ((filp->f_mode & 2) || (permission(inode,2) == 0)) - filp->f_mode |= IOCTL_MODE_BIT; - if (filp->f_mode & 2) - filp->f_mode |= OPEN_WRITE_BIT; if (UFDCS->rawcmd == 1) UFDCS->rawcmd = 2; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c --- v2.4.0-test5/linux/drivers/block/ll_rw_blk.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/block/ll_rw_blk.c Wed Aug 9 14:20:18 2000 @@ -842,10 +842,10 @@ return 0; } -void generic_make_request (request_queue_t *q, int rw, struct buffer_head * bh) +void generic_make_request (int rw, struct buffer_head * bh) { int major = MAJOR(bh->b_rdev); - + request_queue_t *q; if (blk_size[major]) { unsigned long maxsector = (blk_size[major][MINOR(bh->b_rdev)] << 1) + 1; unsigned int sector, count; @@ -877,12 +877,21 @@ * still free to implement/resolve their own stacking * by explicitly returning 0) */ - while (q->make_request_fn(q, rw, bh)) - /* NOTE: we don't repeat the blk_size check even though we now have a - * new device. stacking drivers are expected to know what - * they are doing. - */ + /* NOTE: we don't repeat the blk_size check for each new device. + * Stacking drivers are expected to know what they are doing. + */ + do { q = blk_get_queue(bh->b_rdev); + if (!q) { + printk(KERN_ERR + "generic_make_request: Trying to access nonexistent block-device %s (%ld)\n", + kdevname(bh->b_rdev), bh->b_rsector); + buffer_IO_error(bh); + break; + } + + } + while (q->make_request_fn(q, rw, bh)); } /* This function can be used to request a number of buffers from a block @@ -892,19 +901,11 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]) { struct buffer_head *bh; - request_queue_t *q; unsigned int major; int correct_size; int i; major = MAJOR(bhs[0]->b_dev); - q = blk_get_queue(bhs[0]->b_dev); - if (!q) { - printk(KERN_ERR - "ll_rw_block: Trying to read nonexistent block-device %s (%ld)\n", - kdevname(bhs[0]->b_dev), bhs[0]->b_blocknr); - goto sorry; - } /* Determine correct block size for this device. */ correct_size = BLOCK_SIZE; @@ -948,7 +949,7 @@ bh->b_rdev = bh->b_dev; bh->b_rsector = bh->b_blocknr * (bh->b_size>>9); - generic_make_request(q, rw, bh); + generic_make_request(rw, bh); } return; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/block/loop.c linux/drivers/block/loop.c --- v2.4.0-test5/linux/drivers/block/loop.c Mon Jul 10 16:47:22 2000 +++ linux/drivers/block/loop.c Sun Aug 6 11:43:17 2000 @@ -192,7 +192,7 @@ goto fail; if (aops->prepare_write(file, page, offset, offset+size)) goto unlock; - kaddr = (char*)page_address(page); + kaddr = page_address(page); if ((lo->transfer)(lo, WRITE, kaddr+offset, data, size, IV)) goto write_fail; if (aops->commit_write(file, page, offset, offset+size)) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/block/lvm-snap.c linux/drivers/block/lvm-snap.c --- v2.4.0-test5/linux/drivers/block/lvm-snap.c Mon Jul 10 16:47:22 2000 +++ linux/drivers/block/lvm-snap.c Mon Aug 7 21:01:35 2000 @@ -326,7 +326,7 @@ if (!addr) goto out; iobuf->pagelist[i] = addr; - page = mem_map + MAP_NR(addr); + page = virt_to_page(addr); } #endif diff -u --recursive --new-file v2.4.0-test5/linux/drivers/block/md.c linux/drivers/block/md.c --- v2.4.0-test5/linux/drivers/block/md.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/block/md.c Wed Aug 9 11:43:27 2000 @@ -2741,7 +2741,7 @@ if (md_copy_from_user(&info, (void*)arg, sizeof(info))) err = -EFAULT; else - err = add_new_disk(mddev, (void *)arg); + err = add_new_disk(mddev, &info); goto done_unlock; } case HOT_REMOVE_DISK: diff -u --recursive --new-file v2.4.0-test5/linux/drivers/block/paride/Makefile linux/drivers/block/paride/Makefile --- v2.4.0-test5/linux/drivers/block/paride/Makefile Tue Dec 22 08:29:00 1998 +++ linux/drivers/block/paride/Makefile Sun Aug 6 11:23:40 2000 @@ -12,7 +12,6 @@ MOD_SUB_DIRS := $(SUB_DIRS) ALL_SUB_DIRS := $(SUB_DIRS) -MOD_LIST_NAME := PARIDE_MODULES L_TARGET := paride.a MX_OBJS := LX_OBJS := diff -u --recursive --new-file v2.4.0-test5/linux/drivers/block/raid0.c linux/drivers/block/raid0.c --- v2.4.0-test5/linux/drivers/block/raid0.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/block/raid0.c Mon Aug 7 22:54:48 2000 @@ -28,7 +28,7 @@ static int create_strip_zones (mddev_t *mddev) { int i, c, j, j1, j2; - int current_offset, curr_zone_offset; + unsigned long current_offset, curr_zone_offset; raid0_conf_t *conf = mddev_to_conf(mddev); mdk_rdev_t *smallest, *rdev1, *rdev2, *rdev; @@ -226,12 +226,12 @@ static int raid0_make_request (mddev_t *mddev, int rw, struct buffer_head * bh) { - unsigned int sect_in_chunk, chunksize_bits, chunk, chunk_size; + unsigned int sect_in_chunk, chunksize_bits, chunk_size; raid0_conf_t *conf = mddev_to_conf(mddev); struct raid0_hash *hash; struct strip_zone *zone; mdk_rdev_t *tmp_dev; - unsigned long block, rsect; + unsigned long chunk, block, rsect; chunk_size = mddev->param.chunk_size >> 10; chunksize_bits = ffz(~chunk_size); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/block/raid1.c linux/drivers/block/raid1.c --- v2.4.0-test5/linux/drivers/block/raid1.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/block/raid1.c Wed Aug 9 14:20:18 2000 @@ -274,7 +274,7 @@ } memset(r1_bh, 0, sizeof(*r1_bh)); r1_bh->bh_req.b_page = page; - r1_bh->bh_req.b_data = (char *) page_address(page); + r1_bh->bh_req.b_data = page_address(page); r1_bh->next_r1 = conf->freebuf; conf->freebuf = r1_bh; i++; @@ -448,7 +448,7 @@ { int new_disk = conf->last_used; const int sectors = bh->b_size >> 9; - const long this_sector = bh->b_blocknr * sectors; + const unsigned long this_sector = bh->b_rsector; int disk = new_disk; unsigned long new_distance; unsigned long current_distance; @@ -551,7 +551,6 @@ int disks = MD_SB_DISKS; int i, sum_bhs = 0, sectors; struct mirror_info *mirror; - request_queue_t *q; if (!buffer_locked(bh)) BUG(); @@ -628,8 +627,7 @@ /* bh_req->b_rsector = bh->n_rsector; */ bh_req->b_end_io = raid1_end_request; bh_req->b_private = r1_bh; - q = blk_get_queue(bh_req->b_rdev); - generic_make_request (q, rw, bh_req); + generic_make_request (rw, bh_req); return 0; } @@ -704,8 +702,7 @@ while(bh) { struct buffer_head *bh2 = bh; bh = bh->b_next; - q = blk_get_queue(bh2->b_rdev); - generic_make_request(q, rw, bh2); + generic_make_request(rw, bh2); } return (0); } @@ -1124,7 +1121,6 @@ struct raid1_bh *r1_bh; struct buffer_head *bh; unsigned long flags; - request_queue_t *q; mddev_t *mddev; kdev_t dev; @@ -1206,8 +1202,7 @@ while (mbh) { struct buffer_head *bh1 = mbh; mbh = mbh->b_next; - q = blk_get_queue(bh1->b_rdev); - generic_make_request(q, WRITE, bh1); + generic_make_request(WRITE, bh1); md_sync_acct(bh1->b_rdev, bh1->b_size/512); } } else { @@ -1220,8 +1215,7 @@ printk (REDIRECT_SECTOR, partition_name(bh->b_dev), bh->b_blocknr); bh->b_rdev = bh->b_dev; - q = blk_get_queue(bh->b_rdev); - generic_make_request (q, READ, bh); + generic_make_request(READ, bh); } } @@ -1238,8 +1232,7 @@ printk (REDIRECT_SECTOR, partition_name(bh->b_dev), bh->b_blocknr); bh->b_rdev = bh->b_dev; - q = blk_get_queue(bh->b_rdev); - generic_make_request (q, r1_bh->cmd, bh); + generic_make_request (r1_bh->cmd, bh); } break; } @@ -1348,7 +1341,6 @@ { raid1_conf_t *conf = mddev_to_conf(mddev); struct mirror_info *mirror; - request_queue_t *q; struct raid1_bh *r1_bh; struct buffer_head *bh; int bsize; @@ -1428,15 +1420,14 @@ BUG(); if (!bh->b_data) BUG(); - if (bh->b_data != (char *) page_address(bh->b_page)) + if (bh->b_data != page_address(bh->b_page)) BUG(); bh->b_end_io = end_sync_read; bh->b_private = r1_bh; bh->b_rsector = block_nr<<1; init_waitqueue_head(&bh->b_wait); - q = blk_get_queue(bh->b_rdev); - generic_make_request(q, READ, bh); + generic_make_request(READ, bh); md_sync_acct(bh->b_rdev, bh->b_size/512); return (bsize >> 10); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/block/raid5.c linux/drivers/block/raid5.c --- v2.4.0-test5/linux/drivers/block/raid5.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/block/raid5.c Wed Aug 9 14:20:18 2000 @@ -257,7 +257,7 @@ memset(bh, 0, sizeof (struct buffer_head)); init_waitqueue_head(&bh->b_wait); page = alloc_page(priority); - bh->b_data = (char *) page_address(page); + bh->b_data = page_address(page); if (!bh->b_data) { kfree(bh); return 1; @@ -631,7 +631,7 @@ raid5_conf_t *conf = sh->raid_conf; char *b_data; struct page *b_page; - int block = sh->sector / (sh->size >> 9); + unsigned long block = sh->sector / (sh->size >> 9); b_data = bh->b_data; b_page = bh->b_page; @@ -715,12 +715,13 @@ * Input: a 'big' sector number, * Output: index of the data and parity disk, and the sector # in them. */ -static unsigned long raid5_compute_sector(int r_sector, unsigned int raid_disks, +static unsigned long raid5_compute_sector(unsigned long r_sector, unsigned int raid_disks, unsigned int data_disks, unsigned int * dd_idx, unsigned int * pd_idx, raid5_conf_t *conf) { - unsigned int stripe; - int chunk_number, chunk_offset; + unsigned long stripe; + unsigned long chunk_number; + unsigned int chunk_offset; unsigned long new_sector; int sectors_per_chunk = conf->chunk_size >> 9; @@ -1016,7 +1017,6 @@ int nr_failed_other, int nr_cache_overwrite, int nr_failed_overwrite) { int i, allclean; - request_queue_t *q; unsigned int block; struct buffer_head *bh; int method1 = INT_MAX, method2 = INT_MAX; @@ -1087,21 +1087,18 @@ PRINTK("writing spare %d\n", i); atomic_inc(&sh->nr_pending); bh->b_dev = bh->b_rdev = conf->spare->dev; - q = blk_get_queue(bh->b_rdev); - generic_make_request(q, WRITERAW, bh); + generic_make_request(WRITERAW, bh); } else { #if 0 atomic_inc(&sh->nr_pending); bh->b_dev = bh->b_rdev = conf->disks[i].dev; - q = blk_get_queue(bh->b_rdev); - generic_make_request(q, WRITERAW, bh); + generic_make_request(WRITERAW, bh); #else if (!allclean || (i==sh->pd_idx)) { PRINTK("writing dirty %d\n", i); atomic_inc(&sh->nr_pending); bh->b_dev = bh->b_rdev = conf->disks[i].dev; - q = blk_get_queue(bh->b_rdev); - generic_make_request(q, WRITERAW, bh); + generic_make_request(WRITERAW, bh); } else { PRINTK("not writing clean %d\n", i); raid5_end_request(bh, 1); @@ -1146,8 +1143,7 @@ lock_get_bh(sh->bh_old[i]); atomic_inc(&sh->nr_pending); sh->bh_old[i]->b_dev = sh->bh_old[i]->b_rdev = conf->disks[i].dev; - q = blk_get_queue(sh->bh_old[i]->b_rdev); - generic_make_request(q, READ, sh->bh_old[i]); + generic_make_request(READ, sh->bh_old[i]); atomic_dec(&sh->bh_old[i]->b_count); } PRINTK("handle_stripe() %lu, reading %d old buffers\n", sh->sector, md_atomic_read(&sh->nr_pending)); @@ -1162,7 +1158,6 @@ int nr_failed_other, int nr_cache_overwrite, int nr_failed_overwrite) { int i; - request_queue_t *q; int method1 = INT_MAX; method1 = nr_read - nr_cache_overwrite; @@ -1193,8 +1188,7 @@ lock_get_bh(sh->bh_old[i]); atomic_inc(&sh->nr_pending); sh->bh_old[i]->b_dev = sh->bh_old[i]->b_rdev = conf->disks[i].dev; - q = blk_get_queue(sh->bh_old[i]->b_rdev); - generic_make_request(q, READ, sh->bh_old[i]); + generic_make_request(READ, sh->bh_old[i]); atomic_dec(&sh->bh_old[i]->b_count); } PRINTK("handle_stripe() %lu, phase READ_OLD, pending %d buffers\n", sh->sector, md_atomic_read(&sh->nr_pending)); @@ -1223,8 +1217,7 @@ lock_get_bh(sh->bh_req[i]); atomic_inc(&sh->nr_pending); sh->bh_req[i]->b_dev = sh->bh_req[i]->b_rdev = conf->disks[i].dev; - q = blk_get_queue(sh->bh_req[i]->b_rdev); - generic_make_request(q, READ, sh->bh_req[i]); + generic_make_request(READ, sh->bh_req[i]); atomic_dec(&sh->bh_req[i]->b_count); } PRINTK("handle_stripe() %lu, phase READ, pending %d\n", sh->sector, md_atomic_read(&sh->nr_pending)); @@ -1238,7 +1231,6 @@ int parity, int parity_failed, int nr_cache, int nr_cache_other, int nr_failed_other, int nr_cache_overwrite, int nr_failed_overwrite) { - request_queue_t *q; struct buffer_head *bh; int i, pd_idx; @@ -1261,8 +1253,7 @@ lock_get_bh(bh); atomic_inc(&sh->nr_pending); bh->b_dev = bh->b_rdev = conf->disks[i].dev; - q = blk_get_queue(bh->b_rdev); - generic_make_request(q, READ, bh); + generic_make_request(READ, bh); md_sync_acct(bh->b_rdev, bh->b_size/512); atomic_dec(&sh->bh_old[i]->b_count); } @@ -1291,8 +1282,7 @@ atomic_inc(&sh->nr_pending); lock_get_bh(bh); bh->b_dev = bh->b_rdev = conf->spare->dev; - q = blk_get_queue(bh->b_rdev); - generic_make_request(q, WRITERAW, bh); + generic_make_request(WRITERAW, bh); md_sync_acct(bh->b_rdev, bh->b_size/512); atomic_dec(&bh->b_count); PRINTK("handle_stripe_sync() %lu, phase WRITE, pending %d buffers\n", sh->sector, md_atomic_read(&sh->nr_pending)); @@ -1318,8 +1308,7 @@ lock_get_bh(bh); atomic_inc(&sh->nr_pending); bh->b_dev = bh->b_rdev = conf->disks[pd_idx].dev; - q = blk_get_queue(bh->b_rdev); - generic_make_request(q, WRITERAW, bh); + generic_make_request(WRITERAW, bh); md_sync_acct(bh->b_rdev, bh->b_size/512); atomic_dec(&bh->b_count); PRINTK("handle_stripe_sync() %lu phase WRITE, pending %d buffers\n", @@ -1671,7 +1660,7 @@ tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); tmp->b_size = 4096; tmp->b_page = alloc_page(GFP_KERNEL); - tmp->b_data = (char *)page_address(tmp->b_page); + tmp->b_data = page_address(tmp->b_page); if (!tmp->b_data) goto out; md_clear_page(tmp->b_data); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/block/xd.h linux/drivers/block/xd.h --- v2.4.0-test5/linux/drivers/block/xd.h Mon Jul 10 16:47:22 2000 +++ linux/drivers/block/xd.h Wed Aug 9 13:49:29 2000 @@ -103,7 +103,6 @@ const char *name; } XD_SIGNATURE; -static int xd_setup (char *); #ifndef MODULE static int xd_manual_geo_init (char *command); #endif /* MODULE */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/cdrom/Makefile linux/drivers/cdrom/Makefile --- v2.4.0-test5/linux/drivers/cdrom/Makefile Thu Aug 20 15:17:06 1998 +++ linux/drivers/cdrom/Makefile Sun Aug 6 11:23:40 2000 @@ -53,7 +53,6 @@ # Translate to Rules.make lists. L_TARGET := cdrom.a -MOD_LIST_NAME := CDROM_MODULES L_OBJS := $(sort $(filter-out $(export-objs), $(obj-y))) LX_OBJS := $(sort $(filter $(export-objs), $(obj-y))) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/Config.in linux/drivers/char/Config.in --- v2.4.0-test5/linux/drivers/char/Config.in Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/Config.in Tue Aug 8 09:27:33 2000 @@ -259,8 +259,8 @@ tristate '/dev/agpgart (AGP Support)' CONFIG_AGP $CONFIG_DRM_AGP if [ "$CONFIG_AGP" != "n" ]; then - bool ' Intel 440LX/BX/GX support' CONFIG_AGP_INTEL - bool ' Intel I810/I810 DC100/I810e support' CONFIG_AGP_I810 + bool ' Intel 440LX/BX/GX 840 support' CONFIG_AGP_INTEL + bool ' Intel I810/I815 support' CONFIG_AGP_I810 bool ' VIA chipset support' CONFIG_AGP_VIA bool ' AMD Irongate support' CONFIG_AGP_AMD bool ' Generic SiS support' CONFIG_AGP_SIS diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/Makefile linux/drivers/char/Makefile --- v2.4.0-test5/linux/drivers/char/Makefile Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/Makefile Fri Jul 28 12:33:31 2000 @@ -23,7 +23,7 @@ SUB_DIRS := MOD_SUB_DIRS := $(SUB_DIRS) -ALL_SUB_DIRS := $(SUB_DIRS) ftape joystick pcmcia rio +ALL_SUB_DIRS := $(SUB_DIRS) ftape joystick pcmcia rio drm agp # # This file contains the font map for the default (hardware) font @@ -109,16 +109,7 @@ endif obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o - obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o -ifeq ($(CONFIG_ATARI_DSP56K),y) -S = y -else - ifeq ($(CONFIG_ATARI_DSP56K),m) - SM = y - endif -endif - obj-$(CONFIG_ROCKETPORT) += rocket.o obj-$(CONFIG_MOXA_SMARTIO) += mxser.o obj-$(CONFIG_MOXA_INTELLIO) += moxa.o @@ -135,10 +126,6 @@ obj-$(CONFIG_N_HDLC) += n_hdlc.o obj-$(CONFIG_SPECIALIX) += specialix.o obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o - -# After much ado, we found that an object can safely be declared as -# both a module and into the kernel. Below that is filtered out. -# So this should simply provide the wanted functionality! obj-$(CONFIG_SX) += sx.o generic_serial.o obj-$(CONFIG_RIO) += rio/rio.o generic_serial.o obj-$(CONFIG_SH_SCI) += sh-sci.o generic_serial.o @@ -166,14 +153,6 @@ endif obj-$(CONFIG_BUSMOUSE) += busmouse.o -ifeq ($(CONFIG_BUSMOUSE),y) -M = y -else - ifeq ($(CONFIG_BUSMOUSE),m) - MM = m - endif -endif - obj-$(CONFIG_DTLK) += dtlk.o obj-$(CONFIG_R3964) += n_r3964.o obj-$(CONFIG_APPLICOM) += applicom.o @@ -203,72 +182,17 @@ obj-$(CONFIG_DS1620) += ds1620.o obj-$(CONFIG_INTEL_RNG) += i810_rng.o -# -# for external dependencies in arm/config.in and video/config.in -# -ifeq ($(CONFIG_BUS_I2C),y) - L_I2C=y -else - ifeq ($(CONFIG_BUS_I2C),m) - L_I2C=m - endif -endif - +obj-$(CONFIG_BUS_I2C) += i2c-old.o obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o \ - tda7432.o tda8425.o tda985x.o tda9875.o tea6300.o tea6420.o -ifeq ($(CONFIG_VIDEO_BT848),y) -L_TUNERS=y -else - ifeq ($(CONFIG_VIDEO_BT848),m) - L_TUNERS=m - endif -endif + tda7432.o tda8425.o tda985x.o tda9875.o tea6300.o tea6420.o tuner.o obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o -obj-$(CONFIG_VIDEO_ZR36120) += zoran.o -ifeq ($(CONFIG_VIDEO_ZR36120),y) -L_I2C=y -L_TUNERS=y -L_DECODERS=y -else - ifeq ($(CONFIG_VIDEO_ZR36120),m) - L_I2C=m - L_TUNERS=m - L_DECODERS=m - endif -endif - -obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o -ifeq ($(CONFIG_I2C_PARPORT),y) -L_I2C = y -else - ifeq ($(CONFIG_I2C_PARPORT),m) - L_I2C = m - endif -endif - -obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o -ifeq ($(CONFIG_VIDEO_SAA5249),y) -L_I2C=y -else - ifeq ($(CONFIG_VIDEO_SAA5249),m) - L_I2C=m - endif -endif - +obj-$(CONFIG_VIDEO_ZR36120) += zoran.o i2c-old.o tuner.o saa7110.o saa7111.o saa7185.o +obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o i2c-old.o +obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o i2c-old.o obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o obj-$(CONFIG_VIDEO_BWQCAM) += bw-qcam.o -obj-$(CONFIG_VIDEO_ZORAN) += buz.o -ifeq ($(CONFIG_VIDEO_ZORAN),y) -L_I2C=y -L_DECODERS=y -else - ifeq ($(CONFIG_VIDEO_ZORAN),m) - L_I2C=m - L_DECODERS=m - endif -endif - +obj-$(CONFIG_VIDEO_ZORAN) += buz.o i2c-old.o saa7110.o saa7111.o saa7185.o obj-$(CONFIG_VIDEO_LML33) += bt856.o bt819.o obj-$(CONFIG_VIDEO_PMS) += pms.o obj-$(CONFIG_VIDEO_PLANB) += planb.o @@ -305,24 +229,17 @@ obj-$(CONFIG_H8) += h8.o obj-$(CONFIG_PPDEV) += ppdev.o - -# set when a framegrabber supports external tuners -obj-$(L_TUNERS) += tuner.o - -# set when a framegrabber supports external decoders -obj-$(L_DECODERS) += saa7110.o saa7111.o saa7185.o - -# set when a framegrabber implements i2c support -obj-$(L_I2C) += i2c-old.o - obj-$(CONFIG_DZ) += dz.o obj-$(CONFIG_NWBUTTON) += nwbutton.o obj-$(CONFIG_NWFLASH) += nwflash.o ifeq ($(CONFIG_DRM),y) SUB_DIRS += drm - ALL_SUB_DIRS += drm MOD_SUB_DIRS += drm +else + ifeq ($(CONFIG_DRM),m) + MOD_SUB_DIRS += drm + endif endif ifeq ($(CONFIG_PCMCIA),y) @@ -336,11 +253,9 @@ ifeq ($(CONFIG_AGP), y) SUB_DIRS += agp - ALL_SUB_DIRS += agp MOD_SUB_DIRS += agp else ifeq ($(CONFIG_AGP), m) - ALL_SUB_DIRS += agp MOD_SUB_DIRS += agp endif endif diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/agp/agp.h linux/drivers/char/agp/agp.h --- v2.4.0-test5/linux/drivers/char/agp/agp.h Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/agp/agp.h Tue Aug 8 09:27:33 2000 @@ -181,6 +181,12 @@ #ifndef PCI_DEVICE_ID_INTEL_810_E_1 #define PCI_DEVICE_ID_INTEL_810_E_1 0x7125 #endif +#ifndef PCI_DEVICE_ID_INTEL_815_0 +#define PCI_DEVICE_ID_INTEL_815_0 0x1130 +#endif +#ifndef PCI_DEVICE_ID_INTEL_815_1 +#define PCI_DEVICE_ID_INTEL_815_1 0x1132 +#endif #ifndef PCI_DEVICE_ID_INTEL_82443GX_1 #define PCI_DEVICE_ID_INTEL_82443GX_1 0x71a1 #endif diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/agp/agpgart_be.c linux/drivers/char/agp/agpgart_be.c --- v2.4.0-test5/linux/drivers/char/agp/agpgart_be.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/agp/agpgart_be.c Tue Aug 8 09:27:33 2000 @@ -108,6 +108,9 @@ int agp_backend_acquire(void) { + if (agp_bridge.type == NOT_SUPPORTED) { + return -EINVAL; + } atomic_inc(&agp_bridge.agp_in_use); if (atomic_read(&agp_bridge.agp_in_use) != 1) { @@ -120,6 +123,9 @@ void agp_backend_release(void) { + if (agp_bridge.type == NOT_SUPPORTED) { + return; + } atomic_dec(&agp_bridge.agp_in_use); MOD_DEC_USE_COUNT; } @@ -141,8 +147,8 @@ if (pt == NULL) { return 0; } - atomic_inc(&mem_map[MAP_NR(pt)].count); - set_bit(PG_locked, &mem_map[MAP_NR(pt)].flags); + atomic_inc(&virt_to_page(pt)->count); + set_bit(PG_locked, &virt_to_page(pt)->flags); atomic_inc(&agp_bridge.current_memory_agp); return (unsigned long) pt; } @@ -154,9 +160,9 @@ if (pt == NULL) { return; } - atomic_dec(&mem_map[MAP_NR(pt)].count); - clear_bit(PG_locked, &mem_map[MAP_NR(pt)].flags); - wake_up(&mem_map[MAP_NR(pt)].wait); + atomic_dec(&virt_to_page(pt)->count); + clear_bit(PG_locked, &virt_to_page(pt)->flags); + wake_up(&virt_to_page(pt)->wait); free_page((unsigned long) pt); atomic_dec(&agp_bridge.current_memory_agp); } @@ -224,7 +230,7 @@ { int i; - if (curr == NULL) { + if ((agp_bridge.type == NOT_SUPPORTED) || (curr == NULL)) { return; } if (curr->is_bound == TRUE) { @@ -255,6 +261,9 @@ agp_memory *new; int i; + if (agp_bridge.type == NOT_SUPPORTED) { + return NULL; + } if ((atomic_read(&agp_bridge.current_memory_agp) + page_count) > agp_bridge.max_memory_agp) { return NULL; @@ -334,6 +343,10 @@ void agp_copy_info(agp_kern_info * info) { memset(info, 0, sizeof(agp_kern_info)); + if (agp_bridge.type == NOT_SUPPORTED) { + info->chipset = agp_bridge.type; + return; + } info->version.major = agp_bridge.version->major; info->version.minor = agp_bridge.version->minor; info->device = agp_bridge.dev; @@ -357,7 +370,8 @@ { int ret_val; - if ((curr == NULL) || (curr->is_bound == TRUE)) { + if ((agp_bridge.type == NOT_SUPPORTED) || + (curr == NULL) || (curr->is_bound == TRUE)) { return -EINVAL; } if (curr->is_flushed == FALSE) { @@ -378,7 +392,7 @@ { int ret_val; - if (curr == NULL) { + if ((agp_bridge.type == NOT_SUPPORTED) || (curr == NULL)) { return -EINVAL; } if (curr->is_bound != TRUE) { @@ -541,6 +555,7 @@ int num_entries; int i; void *temp; + struct page *page; /* The generic routines can't handle 2 level gatt's */ if (agp_bridge.size_type == LVL2_APER_SIZE) { @@ -622,9 +637,8 @@ } table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1); - for (i = MAP_NR(table); i < MAP_NR(table_end); i++) { - set_bit(PG_reserved, &mem_map[i].flags); - } + for (page = virt_to_page(table); page < virt_to_page(table_end); page++) + set_bit(PG_reserved, &page->flags); agp_bridge.gatt_table_real = (unsigned long *) table; CACHE_FLUSH(); @@ -633,9 +647,8 @@ CACHE_FLUSH(); if (agp_bridge.gatt_table == NULL) { - for (i = MAP_NR(table); i < MAP_NR(table_end); i++) { - clear_bit(PG_reserved, &mem_map[i].flags); - } + for (page = virt_to_page(table); page < virt_to_page(table_end); page++) + clear_bit(PG_reserved, &page->flags); free_pages((unsigned long) table, page_order); @@ -653,10 +666,10 @@ static int agp_generic_free_gatt_table(void) { - int i; int page_order; char *table, *table_end; void *temp; + struct page *page; temp = agp_bridge.current_size; @@ -691,9 +704,8 @@ table = (char *) agp_bridge.gatt_table_real; table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1); - for (i = MAP_NR(table); i < MAP_NR(table_end); i++) { - clear_bit(PG_reserved, &mem_map[i].flags); - } + for (page = virt_to_page(table); page < virt_to_page(table_end); page++) + clear_bit(PG_reserved, &page->flags); free_pages((unsigned long) agp_bridge.gatt_table_real, page_order); return 0; @@ -791,6 +803,7 @@ void agp_enable(u32 mode) { + if (agp_bridge.type == NOT_SUPPORTED) return; agp_bridge.agp_enable(mode); } @@ -1500,13 +1513,13 @@ if (page_map->real == NULL) { return -ENOMEM; } - set_bit(PG_reserved, &mem_map[MAP_NR(page_map->real)].flags); + set_bit(PG_reserved, &virt_to_page(page_map->real)->flags); CACHE_FLUSH(); page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), PAGE_SIZE); if (page_map->remapped == NULL) { clear_bit(PG_reserved, - &mem_map[MAP_NR(page_map->real)].flags); + &virt_to_page(page_map->real)->flags); free_page((unsigned long) page_map->real); page_map->real = NULL; return -ENOMEM; @@ -1524,7 +1537,7 @@ { iounmap(page_map->remapped); clear_bit(PG_reserved, - &mem_map[MAP_NR(page_map->real)].flags); + &virt_to_page(page_map->real)->flags); free_page((unsigned long) page_map->real); } @@ -2114,6 +2127,12 @@ #endif /* CONFIG_AGP_SIS */ #ifdef CONFIG_AGP_VIA + { PCI_DEVICE_ID_VIA_8371_0, + PCI_VENDOR_ID_VIA, + VIA_APOLLO_SUPER, + "Via", + "Apollo Super", + via_generic_setup }, { PCI_DEVICE_ID_VIA_8501_0, PCI_VENDOR_ID_VIA, VIA_MVP4, @@ -2183,16 +2202,15 @@ * there is a 'generic' bridge entry for this vendor */ if (agp_try_unsupported && agp_bridge_info[i].device_id == 0) { printk(KERN_WARNING PFX "Trying generic %s routines" - " for device id: %x\n", + " for device id: %04x\n", agp_bridge_info[i].vendor_name, pdev->device); agp_bridge.type = agp_bridge_info[i].chipset; return agp_bridge_info[i].chipset_setup (pdev); } - printk(KERN_ERR PFX "Unsupported %s chipset," - " you might want to try " - "agp_try_unsupported=1.\n", - agp_bridge_info[i].vendor_name); + printk(KERN_ERR PFX "Unsupported %s chipset (device id: %04x)," + " you might want to try agp_try_unsupported=1.\n", + agp_bridge_info[i].vendor_name, pdev->device); return -ENODEV; } @@ -2261,6 +2279,27 @@ agp_bridge.type = INTEL_I810; return intel_i810_setup(i810_dev); + case PCI_DEVICE_ID_INTEL_815_0: + /* The i815 can operate either as an i810 style + * integrated device, or as an AGP4X motherboard. + * + * This only addresses the first mode: + */ + i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_815_1, + NULL); + if (i810_dev == NULL) { + printk(KERN_ERR PFX "agpgart: Detected an " + "Intel i815, but could not find the" + " secondary device.\n"); + agp_bridge.type = NOT_SUPPORTED; + return -ENODEV; + } + printk(KERN_INFO PFX "agpgart: Detected an Intel i815 " + "Chipset.\n"); + agp_bridge.type = INTEL_I810; + return intel_i810_setup(i810_dev); + default: break; } @@ -2451,11 +2490,13 @@ AGPGART_VERSION_MAJOR, AGPGART_VERSION_MINOR); ret_val = agp_backend_initialize(); - if (ret_val) + if (ret_val) { + agp_bridge.type = NOT_SUPPORTED; return ret_val; - + } ret_val = agp_frontend_initialize(); if (ret_val) { + agp_bridge.type = NOT_SUPPORTED; agp_backend_cleanup(); return ret_val; } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/bttv-cards.c linux/drivers/char/bttv-cards.c --- v2.4.0-test5/linux/drivers/char/bttv-cards.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/bttv-cards.c Sun Aug 6 12:45:28 2000 @@ -73,11 +73,9 @@ { 0x1123153b, BTTV_TERRATVRADIO, "Terratec TV/Radio+" }, { 0x1200bd11, BTTV_PINNACLERAVE, "Pinnacle PCTV Rave" }, { 0x13eb0070, BTTV_HAUPPAUGE878, "Hauppauge WinTV" }, -#if 0 /* probably wrong */ - { 0x14610002, BTTV_AVERMEDIA98, "Avermedia TVCapture 98" }, -#endif { 0x18501851, BTTV_CHRONOS_VS2, "Chronos Video Shuttle II" }, { 0x18521852, BTTV_TYPHOON_TVIEW, "Typhoon TView TV/FM Tuner" }, + { 0x217d6606, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" }, { 0x263610b4, BTTV_STB2, "STB TV PCI FM, P/N 6000704" }, { 0x3000144f, BTTV_MAGICTVIEW063, "TView 99 (CPH063)" }, { 0x300014ff, BTTV_MAGICTVIEW061, "TView 99 (CPH061)" }, @@ -85,7 +83,10 @@ { 0x300214ff, BTTV_PHOEBE_TVMAS, "Phoebe TV Master" }, { 0x400a15b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV" }, { 0x402010fc, 0 /* no tvcards entry yet */, "I-O Data Co. GV-BCV3/PCI" }, +#if 0 /* probably wrong */ + { 0x14610002, BTTV_AVERMEDIA98, "Avermedia TVCapture 98" }, { 0x6606217d, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" }, +#endif { 0, -1, NULL } }; @@ -116,7 +117,7 @@ 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "AVerMedia TVPhone", 3, 1, 0, 3,15, { 2, 3, 1, 1}, {12, 4,11,11, 0},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, + 1,1,1,1,0,0,0,1, PLL_28, -1 }, { "MATRIX-Vision MV-Delta", 5, 1, -1, 3, 0, { 2, 3, 1, 0, 0},{0 }, 0, 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, @@ -218,7 +219,7 @@ 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "Leadtek WinFast 2000", 3, 1, 0, 2, 0xfff000, { 2, 3, 1, 1,0}, - { 0x621000,0x620100,0x621100,0x620000,0xE210000,0x620000},0, + { 0x621000,0x6ddf07,0x621100,0x620000,0xE210000,0x620000},0, 1,1,1,1,1,0,0,1, PLL_28, -1 }, { "Chronos Video Shuttle II", 3, 3, 0, 2, 0x1800, { 2, 3, 1, 1}, { 0, 0, 0x1000, 0x1000, 0x0800},0, @@ -266,7 +267,7 @@ 0,0,0,0,0,0,0,0, PLL_28, 5 }, { "Terratec TV/Radio+", /* Radio ?? */ 3, 1, 0, 2, 0x1f0000, { 2, 3, 1, 1}, - { 0xe2ffff, 0, 0, 0, 0xe0ffff, 0xe2ffff },0, + { 0xe2ffff, 0xebffff, 0, 0, 0xe0ffff, 0xe2ffff },0, 0,0,0,0,0,0,0,0, PLL_35, 1 }, /* 0x30 */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/bttv-driver.c linux/drivers/char/bttv-driver.c --- v2.4.0-test5/linux/drivers/char/bttv-driver.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/bttv-driver.c Mon Aug 7 21:01:35 2000 @@ -132,8 +132,10 @@ if (!pmd_none(*pmd)) { ptep = pte_offset(pmd, adr); pte = *ptep; - if(pte_present(pte)) - ret = (page_address(pte_page(pte))|(adr&(PAGE_SIZE-1))); + if(pte_present(pte)) { + ret = (unsigned long) page_address(pte_page(pte)); + ret |= (adr & (PAGE_SIZE - 1)); + } } } MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret)); @@ -189,7 +191,7 @@ while (size > 0) { page = kvirt_to_pa(adr); - mem_map_reserve(MAP_NR(__va(page))); + mem_map_reserve(virt_to_page(__va(page))); adr+=PAGE_SIZE; size-=PAGE_SIZE; } @@ -207,7 +209,7 @@ while (size > 0) { page = kvirt_to_pa(adr); - mem_map_unreserve(MAP_NR(__va(page))); + mem_map_unreserve(virt_to_page(__va(page))); adr+=PAGE_SIZE; size-=PAGE_SIZE; } @@ -1157,7 +1159,7 @@ offset = iobuf->offset; page = 0; - pageaddr = virt_to_bus((void*)page_address(iobuf->maplist[page])); + pageaddr = virt_to_bus(page_address(iobuf->maplist[page])); for (line=0; line < (height<<(1^inter)); line++) { if (inter) @@ -1178,13 +1180,13 @@ todo -= bl; offset = 0; page++; - pageaddr = virt_to_bus((void*)page_address(iobuf->maplist[page])); + pageaddr = virt_to_bus(page_address(iobuf->maplist[page])); while (todo>PAGE_SIZE) { *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|PAGE_SIZE); *((*rp)++)=cpu_to_le32(pageaddr); page++; - pageaddr = virt_to_bus((void*)page_address(iobuf->maplist[page])); + pageaddr = virt_to_bus(page_address(iobuf->maplist[page])); } *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|todo); *((*rp)++)=cpu_to_le32(pageaddr); @@ -2112,7 +2114,7 @@ iobuf->locked); printk("bttv%d: hack: pages (bus addr):",btv->nr); for (i = 0; i < iobuf->nr_pages; i++) { - printk(" %lx", virt_to_bus((void*)page_address(iobuf->maplist[i]))); + printk(" %lx", virt_to_bus(page_address(iobuf->maplist[i]))); } printk("\n"); @@ -3032,7 +3034,7 @@ struct bttv *btv = PCI_GET_DRIVER_DATA(pci_dev); /* unregister i2c_bus */ - if (btv->i2c_ok) + if (0 == btv->i2c_ok) i2c_bit_del_bus(&btv->i2c_adap); /* turn off all capturing, DMA and IRQs */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/bttv.h linux/drivers/char/bttv.h --- v2.4.0-test5/linux/drivers/char/bttv.h Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/bttv.h Sun Aug 6 12:45:28 2000 @@ -21,7 +21,7 @@ #ifndef _BTTV_H_ #define _BTTV_H_ -#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,37) +#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,38) #ifndef PCI_GET_DRIVER_DATA # define PCI_GET_DRIVER_DATA(pdev) ((pdev)->driver_data) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/busmouse.c linux/drivers/char/busmouse.c --- v2.4.0-test5/linux/drivers/char/busmouse.c Fri Jul 14 12:12:08 2000 +++ linux/drivers/char/busmouse.c Wed Aug 9 14:11:11 2000 @@ -172,12 +172,10 @@ busmouse_fasync(-1, file, 0); if (--mse->active == 0) { - if (mse->ops) { - if (mse->ops->release) - ret = mse->ops->release(inode, file); - if (mse->ops->owner) - __MOD_DEC_USE_COUNT(mse->ops->owner); - } + if (mse->ops->release) + ret = mse->ops->release(inode, file); + if (mse->ops->owner) + __MOD_DEC_USE_COUNT(mse->ops->owner); mse->ready = 0; } unlock_kernel(); @@ -189,7 +187,7 @@ { struct busmouse_data *mse; unsigned int mousedev; - int ret = -ENODEV; + int ret; mousedev = DEV_TO_MOUSE(inode->i_rdev); if (mousedev >= NR_MICE) @@ -197,13 +195,15 @@ down(&mouse_sem); mse = busmouse_data[mousedev]; - if (!mse) - /* shouldn't happen, but... */ + ret = -ENODEV; + if (!mse || !mse->ops) /* shouldn't happen, but... */ + goto end; + + if (mse->ops->owner && !try_inc_mod_count(mse->ops->owner)) goto end; - - if (mse->ops && mse->ops->owner) - __MOD_INC_USE_COUNT(mse->ops->owner); - if (mse->ops && mse->ops->open) { + + ret = 0; + if (mse->ops->open) { ret = mse->ops->open(inode, file); if (ret && mse->ops->owner) __MOD_DEC_USE_COUNT(mse->ops->owner); @@ -222,10 +222,7 @@ mse->ready = 0; mse->dxpos = 0; mse->dypos = 0; - if (mse->ops) - mse->buttons = mse->ops->init_button_state; - else - mse->buttons = 7; + mse->buttons = mse->ops->init_button_state; spin_unlock_irq(&mse->lock); end: diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/buz.c linux/drivers/char/buz.c --- v2.4.0-test5/linux/drivers/char/buz.c Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/buz.c Mon Aug 7 21:01:35 2000 @@ -199,7 +199,7 @@ zr->v4l_gbuf[i].fbuffer_phys = virt_to_phys(mem); zr->v4l_gbuf[i].fbuffer_bus = virt_to_bus(mem); for (off = 0; off < v4l_bufsize; off += PAGE_SIZE) - mem_map_reserve(MAP_NR(mem + off)); + mem_map_reserve(virt_to_page(mem + off)); DEBUG(printk(BUZ_INFO ": V4L frame %d mem 0x%x (bus: 0x%x=%d)\n", i, mem, virt_to_bus(mem), virt_to_bus(mem))); } else { return -ENOBUFS; @@ -221,7 +221,7 @@ mem = zr->v4l_gbuf[i].fbuffer; for (off = 0; off < v4l_bufsize; off += PAGE_SIZE) - mem_map_unreserve(MAP_NR(mem + off)); + mem_map_unreserve(virt_to_page(mem + off)); kfree((void *) zr->v4l_gbuf[i].fbuffer); zr->v4l_gbuf[i].fbuffer = NULL; } @@ -286,7 +286,7 @@ zr->jpg_gbuf[i].frag_tab[0] = virt_to_bus((void *) mem); zr->jpg_gbuf[i].frag_tab[1] = ((zr->jpg_bufsize / 4) << 1) | 1; for (off = 0; off < zr->jpg_bufsize; off += PAGE_SIZE) - mem_map_reserve(MAP_NR(mem + off)); + mem_map_reserve(virt_to_page(mem + off)); } else { /* jpg_bufsize is alreay page aligned */ for (j = 0; j < zr->jpg_bufsize / PAGE_SIZE; j++) { @@ -297,7 +297,7 @@ } zr->jpg_gbuf[i].frag_tab[2 * j] = virt_to_bus((void *) mem); zr->jpg_gbuf[i].frag_tab[2 * j + 1] = (PAGE_SIZE / 4) << 1; - mem_map_reserve(MAP_NR(mem)); + mem_map_reserve(virt_to_page(mem)); } zr->jpg_gbuf[i].frag_tab[2 * j - 1] |= 1; @@ -329,7 +329,7 @@ if (zr->jpg_gbuf[i].frag_tab[0]) { mem = (unsigned char *) bus_to_virt(zr->jpg_gbuf[i].frag_tab[0]); for (off = 0; off < zr->jpg_bufsize; off += PAGE_SIZE) - mem_map_unreserve(MAP_NR(mem + off)); + mem_map_unreserve(virt_to_page(mem + off)); kfree((void *) mem); zr->jpg_gbuf[i].frag_tab[0] = 0; zr->jpg_gbuf[i].frag_tab[1] = 0; @@ -338,7 +338,7 @@ for (j = 0; j < zr->jpg_bufsize / PAGE_SIZE; j++) { if (!zr->jpg_gbuf[i].frag_tab[2 * j]) break; - mem_map_unreserve(MAP_NR(bus_to_virt(zr->jpg_gbuf[i].frag_tab[2 * j]))); + mem_map_unreserve(virt_to_page(bus_to_virt(zr->jpg_gbuf[i].frag_tab[2 * j]))); free_page((unsigned long) bus_to_virt(zr->jpg_gbuf[i].frag_tab[2 * j])); zr->jpg_gbuf[i].frag_tab[2 * j] = 0; zr->jpg_gbuf[i].frag_tab[2 * j + 1] = 0; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/console.c linux/drivers/char/console.c --- v2.4.0-test5/linux/drivers/char/console.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/console.c Wed Aug 9 14:18:26 2000 @@ -586,12 +586,12 @@ } if (redraw) { + int update; set_origin(currcons); - if (sw->con_switch(vc_cons[currcons].d) && vcmode != KD_GRAPHICS) { - /* Update the screen contents */ - set_palette(currcons); + update = sw->con_switch(vc_cons[currcons].d); + set_palette(currcons); + if (update && vcmode != KD_GRAPHICS) do_update_region(currcons, origin, screenbuf_size/2); - } } set_cursor(currcons); if (is_switch) { @@ -2674,6 +2674,7 @@ console_blanked = 0; if (console_blank_hook) console_blank_hook(0); + set_palette(currcons); if (sw->con_blank(vc_cons[currcons].d, 0)) /* Low-level driver cannot restore -> do it ourselves */ update_screen(fg_console); @@ -2940,7 +2941,9 @@ EXPORT_SYMBOL(vc_resize); EXPORT_SYMBOL(fg_console); EXPORT_SYMBOL(console_blank_hook); - +#ifdef CONFIG_VT +EXPORT_SYMBOL(vt_cons); +#endif #ifndef VT_SINGLE_DRIVER EXPORT_SYMBOL(take_over_console); EXPORT_SYMBOL(give_up_console); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/cpia.c linux/drivers/char/cpia.c --- v2.4.0-test5/linux/drivers/char/cpia.c Mon Jun 19 16:31:59 2000 +++ linux/drivers/char/cpia.c Mon Aug 7 21:01:35 2000 @@ -199,9 +199,10 @@ if (!pmd_none(*pmd)) { ptep = pte_offset(pmd, adr); pte = *ptep; - if (pte_present(pte)) - ret = page_address(pte_page(pte)) | - (adr & (PAGE_SIZE-1)); + if (pte_present(pte)) { + ret = (unsigned long) page_address(pte_page(pte)); + ret |= (adr & (PAGE_SIZE-1)); + } } } return ret; @@ -238,7 +239,7 @@ adr = (unsigned long) mem; while (size > 0) { page = kvirt_to_pa(adr); - mem_map_reserve(MAP_NR(__va(page))); + mem_map_reserve(virt_to_page(__va(page))); adr += PAGE_SIZE; if (size > PAGE_SIZE) size -= PAGE_SIZE; @@ -262,7 +263,7 @@ adr = (unsigned long) mem; while (size > 0) { page = kvirt_to_pa(adr); - mem_map_unreserve(MAP_NR(__va(page))); + mem_map_unreserve(virt_to_page(__va(page))); adr += PAGE_SIZE; if (size > PAGE_SIZE) size -= PAGE_SIZE; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/drm/Config.in linux/drivers/char/drm/Config.in --- v2.4.0-test5/linux/drivers/char/drm/Config.in Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/drm/Config.in Tue Aug 8 09:27:33 2000 @@ -5,8 +5,8 @@ # Direct Rendering Infrastructure (DRI) in XFree86 4.x. # -tristate 'Direct Rendering Manager (XFree86 DRI support)' CONFIG_DRM -if [ "$CONFIG_DRM" = "y" ]; then +bool 'Direct Rendering Manager (XFree86 DRI support)' CONFIG_DRM +if [ "$CONFIG_DRM" != "n" ]; then tristate ' 3dfx Banshee/Voodoo3+' CONFIG_DRM_TDFX tristate ' 3dlabs GMX 2000' CONFIG_DRM_GAMMA tristate ' ATI Rage 128' CONFIG_DRM_R128 diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/drm/Makefile linux/drivers/char/drm/Makefile --- v2.4.0-test5/linux/drivers/char/drm/Makefile Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/drm/Makefile Thu Aug 3 17:19:01 2000 @@ -3,58 +3,69 @@ # the Direct Rendering Infrastructure (DRI) in XFree86 4.x. # -O_TARGET = drm.o +# drm.o is a fake target -- it is never built +# The real targets are in the module-list +O_TARGET := drm.o +module-list := gamma.o tdfx.o r128.o ffb.o mga.o i810.o +export-objs := $(patsubst %.o,%_drv.o,$(module-list)) + +# libs-objs are included in every module so that radical changes to the +# architecture of the DRM support library can be made at a later time. +# +# The downside is that each module is larger, and a system that uses +# more than one module (i.e., a dual-head system) will use more memory +# (but a system that uses exactly one module will use the same amount of +# memory). +# +# The upside is that if the DRM support library ever becomes insufficient +# for new families of cards, a new library can be implemented for those new +# cards without impacting the drivers for the old cards. This is significant, +# because testing architectural changes to old cards may be impossible, and +# may delay the implementation of a better architecture. We've traded slight +# memory waste (in the dual-head case) for greatly improved long-term +# maintainability. +# +lib-objs := init.o memory.o proc.o auth.o context.o drawable.o bufs.o +lib-objs += lists.o lock.o ioctl.o fops.o vm.o dma.o ctxbitmap.o -export-objs = drm_syms.o -list-multi = drm.o gamma.o tdfx.o r128.o ffb.o mga.o i810.o -drm-objs = init.o memory.o proc.o auth.o context.o \ - drawable.o bufs.o lists.o lock.o ioctl.o \ - fops.o vm.o dma.o ctxbitmap.o drm_syms.o -gamma-objs = gamma_drv.o gamma_dma.o -tdfx-objs = tdfx_drv.o tdfx_context.o -r128-objs = r128_drv.o r128_context.o r128_dma.o r128_bufs.o -ffb-objs = ffb_drv.o ffb_context.o -mga-objs = mga_drv.o mga_context.o mga_dma.o mga_bufs.o mga_state.o -i810-objs = i810_drv.o i810_context.o i810_dma.o i810_bufs.o - -ifeq ($(CONFIG_AGP), y) - drm-objs += agpsupport.o +ifeq ($(CONFIG_AGP),y) + lib-objs += agpsupport.o else - ifeq ($(CONFIG_AGP), m) - drm-objs += agpsupport.o + ifeq ($(CONFIG_AGP),m) + lib-objs += agpsupport.o endif endif -obj-$(CONFIG_DRM) += drm.o -obj-$(CONFIG_DRM_GAMMA) += gamma.o -obj-$(CONFIG_DRM_TDFX) += tdfx.o -obj-$(CONFIG_DRM_R128) += r128.o -obj-$(CONFIG_DRM_FFB) += ffb.o -obj-$(CONFIG_DRM_MGA) += mga.o -obj-$(CONFIG_DRM_I810) += i810.o - - -# Extract lists of the multi-part drivers. -# The 'int-*' lists are the intermediate files used to build the multi's. -multi-y := $(filter $(list-multi), $(obj-y)) -multi-m := $(filter $(list-multi), $(obj-m)) -int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs))) -int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs))) - -# Files that are both resident and modular: remove from modular. -obj-m := $(filter-out $(obj-y), $(obj-m)) -int-m := $(filter-out $(int-y), $(int-m)) +gamma-objs := $(lib-objs) gamma_drv.o gamma_dma.o +tdfx-objs := $(lib-objs) tdfx_drv.o tdfx_context.o +r128-objs := $(lib-objs) r128_drv.o r128_dma.o r128_context.o r128_bufs.o +ffb-objs := $(lib-objs) ffb_drv.o ffb_context.o +mga-objs := $(lib-objs) mga_drv.o mga_dma.o mga_context.o mga_bufs.o \ + mga_state.o +i810-objs := $(lib-objs) i810_drv.o i810_dma.o i810_context.o i810_bufs.o + +obj-$(CONFIG_DRM_GAMMA) += gamma.o $(gamma-objs) +obj-$(CONFIG_DRM_TDFX) += tdfx.o $(tdfx-objs) +obj-$(CONFIG_DRM_R128) += r128.o $(r128-objs) +obj-$(CONFIG_DRM_FFB) += ffb.o $(ffb-objs) + +ifneq ($CONFIG_AGP),) +obj-$(CONFIG_DRM_MGA) += mga.o $(mga-objs) +obj-$(CONFIG_DRM_I810) += i810.o $(i810-objs) +endif + +# Take module names out of obj-y and int-m -# Take multi-part drivers out of obj-y and put components in. -obj-y := $(filter-out $(list-multi), $(obj-y)) $(int-y) +obj-y := $(filter-out $(module-list), $(obj-y)) +int-m := $(filter-out $(module-list), $(obj-m)) # Translate to Rules.make lists. -O_OBJS := $(filter-out $(export-objs), $(obj-y)) -OX_OBJS := $(filter $(export-objs), $(obj-y)) -M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m))) -MX_OBJS := $(sort $(filter $(export-objs), $(obj-m))) -MI_OBJS := $(sort $(filter-out $(export-objs), $(int-m))) -MIX_OBJS := $(sort $(filter $(export-objs), $(int-m))) + +O_OBJS := $(filter-out $(export-objs), $(obj-y)) +OX_OBJS := $(filter $(export-objs), $(obj-y)) +M_OBJS := $(sort $(filter $(module-list), $(obj-m))) +MI_OBJS := $(sort $(filter-out $(export-objs), $(int-m))) +MIX_OBJS := $(sort $(filter $(export-objs), $(int-m))) include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/drm/README.drm linux/drivers/char/drm/README.drm --- v2.4.0-test5/linux/drivers/char/drm/README.drm Wed Dec 8 14:11:25 1999 +++ linux/drivers/char/drm/README.drm Tue Aug 8 09:27:33 2000 @@ -1,3 +1,7 @@ +************************************************************ +* For the very latest on DRI development, please see: * +* http://dri.sourceforge.net/ * +************************************************************ The Direct Rendering Manager (drm) is a device-independent kernel-level device driver that provides support for the XFree86 Direct Rendering @@ -36,6 +40,7 @@ A Security Analysis of the Direct Rendering Infrastructure http://precisioninsight.com/dr/security.html - - -$XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/README.drm,v 1.2 1999/09/27 14:59:24 dawes Exp $ +************************************************************ +* For the very latest on DRI development, please see: * +* http://dri.sourceforge.net/ * +************************************************************ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/drm/agpsupport.c linux/drivers/char/drm/agpsupport.c --- v2.4.0-test5/linux/drivers/char/drm/agpsupport.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/drm/agpsupport.c Tue Aug 8 09:27:33 2000 @@ -30,6 +30,7 @@ #define __NO_VERSION__ #include "drmP.h" +#include drm_agp_func_t drm_agp = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; @@ -286,23 +287,40 @@ return NULL; memset((void *)head, 0, sizeof(*head)); (*drm_agp.copy_info)(&head->agp_info); + if (head->agp_info.chipset == NOT_SUPPORTED) { + drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS); + return NULL; + } head->memory = NULL; switch (head->agp_info.chipset) { - case INTEL_GENERIC: head->chipset = "Intel"; break; - case INTEL_LX: head->chipset = "Intel 440LX"; break; - case INTEL_BX: head->chipset = "Intel 440BX"; break; - case INTEL_GX: head->chipset = "Intel 440GX"; break; - case INTEL_I810: head->chipset = "Intel i810"; break; - case VIA_GENERIC: head->chipset = "VIA"; break; - case VIA_VP3: head->chipset = "VIA VP3"; break; - case VIA_MVP3: head->chipset = "VIA MVP3"; break; - case VIA_APOLLO_PRO: head->chipset = "VIA Apollo Pro"; break; - case SIS_GENERIC: head->chipset = "SiS"; break; - case AMD_GENERIC: head->chipset = "AMD"; break; - case AMD_IRONGATE: head->chipset = "AMD Irongate"; break; - case ALI_GENERIC: head->chipset = "ALi"; break; - case ALI_M1541: head->chipset = "ALi M1541"; break; - default: + case INTEL_GENERIC: head->chipset = "Intel"; break; + case INTEL_LX: head->chipset = "Intel 440LX"; break; + case INTEL_BX: head->chipset = "Intel 440BX"; break; + case INTEL_GX: head->chipset = "Intel 440GX"; break; + case INTEL_I810: head->chipset = "Intel i810"; break; + +#if LINUX_VERSION_CODE >= 0x020400 + case INTEL_I840: head->chipset = "Intel i840"; break; +#endif + + case VIA_GENERIC: head->chipset = "VIA"; break; + case VIA_VP3: head->chipset = "VIA VP3"; break; + case VIA_MVP3: head->chipset = "VIA MVP3"; break; + +#if LINUX_VERSION_CODE >= 0x020400 + case VIA_MVP4: head->chipset = "VIA MVP4"; break; + case VIA_APOLLO_SUPER: head->chipset = "VIA Apollo Super"; + break; +#endif + + case VIA_APOLLO_PRO: head->chipset = "VIA Apollo Pro"; + break; + case SIS_GENERIC: head->chipset = "SiS"; break; + case AMD_GENERIC: head->chipset = "AMD"; break; + case AMD_IRONGATE: head->chipset = "AMD Irongate"; break; + case ALI_GENERIC: head->chipset = "ALi"; break; + case ALI_M1541: head->chipset = "ALi M1541"; break; + default: head->chipset = "Unknown"; break; } DRM_INFO("AGP %d.%d on %s @ 0x%08lx %dMB\n", head->agp_info.version.major, diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/drm/auth.c linux/drivers/char/drm/auth.c --- v2.4.0-test5/linux/drivers/char/drm/auth.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/drm/auth.c Mon Jul 31 10:16:25 2000 @@ -45,8 +45,6 @@ down(&dev->struct_sem); for (pt = dev->magiclist[hash].head; pt; pt = pt->next) { - if (pt->priv->authenticated) - continue; if (pt->magic == magic) { retval = pt->priv; break; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/drm/drmP.h linux/drivers/char/drm/drmP.h --- v2.4.0-test5/linux/drivers/char/drm/drmP.h Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/drm/drmP.h Wed Aug 9 19:00:58 2000 @@ -44,6 +44,9 @@ #include #include #include +#include +#include /* For (un)lock_kernel */ +#include #include #include #include @@ -137,6 +140,11 @@ #define module_exit(x) void cleanup_module(void) { x(); } #endif + /* virt_to_page added in 2.4.0-test6 */ +#if LINUX_VERSION_CODE < 0x020400 +#define virt_to_page(kaddr) (mem_map + MAP_NR(kaddr)) +#endif + /* Generic cmpxchg added in 2.3.x */ #ifndef __HAVE_ARCH_CMPXCHG /* Include this here so that driver can be @@ -497,8 +505,8 @@ /* Context support */ int irq; /* Interrupt used by board */ __volatile__ long context_flag; /* Context swapping flag */ - __volatile__ long interrupt_flag; /* Interruption handler flag */ - __volatile__ long dma_flag; /* DMA dispatch flag */ + __volatile__ long interrupt_flag; /* Interruption handler flag */ + __volatile__ long dma_flag; /* DMA dispatch flag */ struct timer_list timer; /* Timer for delaying ctx switch */ wait_queue_head_t context_wait; /* Processes waiting on ctx switch */ int last_checked; /* Last context checked for DMA */ @@ -556,6 +564,9 @@ extern unsigned long drm_vm_shm_nopage(struct vm_area_struct *vma, unsigned long address, int write_access); +extern unsigned long drm_vm_shm_nopage_lock(struct vm_area_struct *vma, + unsigned long address, + int write_access); extern unsigned long drm_vm_dma_nopage(struct vm_area_struct *vma, unsigned long address, int write_access); @@ -567,6 +578,9 @@ extern struct page *drm_vm_shm_nopage(struct vm_area_struct *vma, unsigned long address, int write_access); +extern struct page *drm_vm_shm_nopage_lock(struct vm_area_struct *vma, + unsigned long address, + int write_access); extern struct page *drm_vm_dma_nopage(struct vm_area_struct *vma, unsigned long address, int write_access); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/drm/drm_syms.c linux/drivers/char/drm/drm_syms.c --- v2.4.0-test5/linux/drivers/char/drm/drm_syms.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/drm/drm_syms.c Wed Dec 31 16:00:00 1969 @@ -1,146 +0,0 @@ - -#include "drmP.h" - -/* Misc. support (init.c) */ -EXPORT_SYMBOL(drm_flags); -EXPORT_SYMBOL(drm_parse_options); -EXPORT_SYMBOL(drm_cpu_valid); - -/* Device support (fops.c) */ -EXPORT_SYMBOL(drm_open_helper); -EXPORT_SYMBOL(drm_flush); -EXPORT_SYMBOL(drm_release); -EXPORT_SYMBOL(drm_fasync); -EXPORT_SYMBOL(drm_read); -EXPORT_SYMBOL(drm_write_string); -EXPORT_SYMBOL(drm_poll); - -/* Mapping support (vm.c) */ -#if LINUX_VERSION_CODE < 0x020317 -EXPORT_SYMBOL(drm_vm_nopage); -EXPORT_SYMBOL(drm_vm_shm_nopage); -EXPORT_SYMBOL(drm_vm_dma_nopage); -#else -/* Return type changed in 2.3.23 */ -EXPORT_SYMBOL(drm_vm_nopage); -EXPORT_SYMBOL(drm_vm_shm_nopage); -EXPORT_SYMBOL(drm_vm_dma_nopage); -#endif - -EXPORT_SYMBOL(drm_vm_open); -EXPORT_SYMBOL(drm_vm_close); -EXPORT_SYMBOL(drm_mmap_dma); -EXPORT_SYMBOL(drm_mmap); - -/* Proc support (proc.c) */ -EXPORT_SYMBOL(drm_proc_init); -EXPORT_SYMBOL(drm_proc_cleanup); - -/* Memory management support (memory.c) */ -EXPORT_SYMBOL(drm_mem_init); -EXPORT_SYMBOL(drm_mem_info); -EXPORT_SYMBOL(drm_alloc); -EXPORT_SYMBOL(drm_realloc); -EXPORT_SYMBOL(drm_strdup); -EXPORT_SYMBOL(drm_strfree); -EXPORT_SYMBOL(drm_free); -EXPORT_SYMBOL(drm_alloc_pages); -EXPORT_SYMBOL(drm_free_pages); -EXPORT_SYMBOL(drm_ioremap); -EXPORT_SYMBOL(drm_ioremapfree); -#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE) -EXPORT_SYMBOL(drm_alloc_agp); -EXPORT_SYMBOL(drm_free_agp); -EXPORT_SYMBOL(drm_bind_agp); -EXPORT_SYMBOL(drm_unbind_agp); -#endif - -/* Buffer management support (bufs.c) */ -EXPORT_SYMBOL(drm_order); -EXPORT_SYMBOL(drm_addmap); -EXPORT_SYMBOL(drm_addbufs); -EXPORT_SYMBOL(drm_infobufs); -EXPORT_SYMBOL(drm_markbufs); -EXPORT_SYMBOL(drm_freebufs); -EXPORT_SYMBOL(drm_mapbufs); - -/* Buffer list management support (lists.c) */ -EXPORT_SYMBOL(drm_waitlist_create); -EXPORT_SYMBOL(drm_waitlist_destroy); -EXPORT_SYMBOL(drm_waitlist_put); -EXPORT_SYMBOL(drm_waitlist_get); -EXPORT_SYMBOL(drm_freelist_create); -EXPORT_SYMBOL(drm_freelist_destroy); -EXPORT_SYMBOL(drm_freelist_put); -EXPORT_SYMBOL(drm_freelist_get); - -/* DMA support (gen_dma.c) */ -EXPORT_SYMBOL(drm_dma_setup); -EXPORT_SYMBOL(drm_dma_takedown); -EXPORT_SYMBOL(drm_free_buffer); -EXPORT_SYMBOL(drm_reclaim_buffers); -EXPORT_SYMBOL(drm_context_switch); -EXPORT_SYMBOL(drm_context_switch_complete); -EXPORT_SYMBOL(drm_clear_next_buffer); -EXPORT_SYMBOL(drm_select_queue); -EXPORT_SYMBOL(drm_dma_enqueue); -EXPORT_SYMBOL(drm_dma_get_buffers); -#if DRM_DMA_HISTOGRAM -EXPORT_SYMBOL(drm_histogram_slot); -EXPORT_SYMBOL(drm_histogram_compute); -#endif - -/* Misc. IOCTL support (ioctl.c) */ -EXPORT_SYMBOL(drm_irq_busid); -EXPORT_SYMBOL(drm_getunique); -EXPORT_SYMBOL(drm_setunique); - -/* Context IOCTL support (context.c) */ -EXPORT_SYMBOL(drm_resctx); -EXPORT_SYMBOL(drm_addctx); -EXPORT_SYMBOL(drm_modctx); -EXPORT_SYMBOL(drm_getctx); -EXPORT_SYMBOL(drm_switchctx); -EXPORT_SYMBOL(drm_newctx); -EXPORT_SYMBOL(drm_rmctx); - -/* Drawable IOCTL support (drawable.c) */ -EXPORT_SYMBOL(drm_adddraw); -EXPORT_SYMBOL(drm_rmdraw); - -/* Authentication IOCTL support (auth.c) */ -EXPORT_SYMBOL(drm_add_magic); -EXPORT_SYMBOL(drm_remove_magic); -EXPORT_SYMBOL(drm_getmagic); -EXPORT_SYMBOL(drm_authmagic); - -/* Locking IOCTL support (lock.c) */ -EXPORT_SYMBOL(drm_block); -EXPORT_SYMBOL(drm_unblock); -EXPORT_SYMBOL(drm_lock_take); -EXPORT_SYMBOL(drm_lock_transfer); -EXPORT_SYMBOL(drm_lock_free); -EXPORT_SYMBOL(drm_finish); -EXPORT_SYMBOL(drm_flush_unblock); -EXPORT_SYMBOL(drm_flush_block_and_flush); - -/* Context Bitmap support (ctxbitmap.c) */ -EXPORT_SYMBOL(drm_ctxbitmap_init); -EXPORT_SYMBOL(drm_ctxbitmap_cleanup); -EXPORT_SYMBOL(drm_ctxbitmap_next); -EXPORT_SYMBOL(drm_ctxbitmap_free); - -/* AGP/GART support (agpsupport.c) */ -#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE) -EXPORT_SYMBOL(drm_agp); -EXPORT_SYMBOL(drm_agp_init); -EXPORT_SYMBOL(drm_agp_uninit); -EXPORT_SYMBOL(drm_agp_acquire); -EXPORT_SYMBOL(drm_agp_release); -EXPORT_SYMBOL(drm_agp_enable); -EXPORT_SYMBOL(drm_agp_info); -EXPORT_SYMBOL(drm_agp_alloc); -EXPORT_SYMBOL(drm_agp_free); -EXPORT_SYMBOL(drm_agp_unbind); -EXPORT_SYMBOL(drm_agp_bind); -#endif diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/drm/gamma_drv.c linux/drivers/char/drm/gamma_drv.c --- v2.4.0-test5/linux/drivers/char/drm/gamma_drv.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/drm/gamma_drv.c Tue Aug 8 09:27:34 2000 @@ -30,9 +30,6 @@ */ #include -#include -#include -#include /* For (un)lock_kernel */ #include "drmP.h" #include "gamma_drv.h" @@ -53,8 +50,8 @@ static drm_device_t gamma_device; static struct file_operations gamma_fops = { -#if LINUX_VERSION_CODE >= 0x020322 - /* This started being used approx. 2.3.34 */ +#if LINUX_VERSION_CODE >= 0x020400 + /* This started being used during 2.4.0-test */ owner: THIS_MODULE, #endif open: gamma_open, @@ -342,7 +339,7 @@ /* gamma_init is called via init_module at module load time, or via * linux/init/main.c (this is not currently supported). */ -int gamma_init(void) +static int gamma_init(void) { int retcode; drm_device_t *dev = &gamma_device; @@ -383,7 +380,7 @@ /* gamma_cleanup is called via cleanup_module at module unload time. */ -void gamma_cleanup(void) +static void gamma_cleanup(void) { drm_device_t *dev = &gamma_device; @@ -443,6 +440,9 @@ DRM_DEBUG("open_count = %d\n", dev->open_count); if (!(retcode = drm_open_helper(inode, filp, dev))) { +#if LINUX_VERSION_CODE < 0x020333 + MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */ +#endif atomic_inc(&dev->total_open); spin_lock(&dev->count_lock); if (!dev->open_count++) { @@ -465,6 +465,9 @@ DRM_DEBUG("open_count = %d\n", dev->open_count); if (!(retcode = drm_release(inode, filp))) { +#if LINUX_VERSION_CODE < 0x020333 + MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */ +#endif atomic_inc(&dev->total_close); spin_lock(&dev->count_lock); if (!--dev->open_count) { @@ -477,9 +480,8 @@ return -EBUSY; } spin_unlock(&dev->count_lock); - retcode = gamma_takedown(dev); unlock_kernel(); - return retcode; + return gamma_takedown(dev); } spin_unlock(&dev->count_lock); } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/drm/i810_context.c linux/drivers/char/drm/i810_context.c --- v2.4.0-test5/linux/drivers/char/drm/i810_context.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/drm/i810_context.c Thu Aug 3 17:19:01 2000 @@ -29,8 +29,6 @@ * */ -#include - #define __NO_VERSION__ #include "drmP.h" #include "i810_drv.h" diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/drm/i810_dma.c linux/drivers/char/drm/i810_dma.c --- v2.4.0-test5/linux/drivers/char/drm/i810_dma.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/drm/i810_dma.c Mon Aug 7 21:01:36 2000 @@ -33,10 +33,7 @@ #define __NO_VERSION__ #include "drmP.h" #include "i810_drv.h" - #include /* For task queue support */ -#include -#include /* in case we don't have a 2.3.99-pre6 kernel or later: */ #ifndef VM_DONTCOPY @@ -158,16 +155,16 @@ int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma) { - drm_file_t *priv = filp->private_data; - drm_device_t *dev; - drm_i810_private_t *dev_priv; - drm_buf_t *buf; + drm_file_t *priv = filp->private_data; + drm_device_t *dev; + drm_i810_private_t *dev_priv; + drm_buf_t *buf; drm_i810_buf_priv_t *buf_priv; lock_kernel(); - dev = priv->dev; + dev = priv->dev; dev_priv = dev->dev_private; - buf = dev_priv->mmap_buffer; + buf = dev_priv->mmap_buffer; buf_priv = buf->dev_private; vma->vm_flags |= (VM_IO | VM_DONTCOPY); @@ -285,8 +282,8 @@ if(address == 0UL) return 0; - atomic_inc(&mem_map[MAP_NR((void *) address)].count); - set_bit(PG_locked, &mem_map[MAP_NR((void *) address)].flags); + atomic_inc(&virt_to_page(address)->count); + set_bit(PG_locked, &virt_to_page(address)->flags); return address; } @@ -296,9 +293,9 @@ if(page == 0UL) return; - atomic_dec(&mem_map[MAP_NR((void *) page)].count); - clear_bit(PG_locked, &mem_map[MAP_NR((void *) page)].flags); - wake_up(&mem_map[MAP_NR((void *) page)].wait); + atomic_dec(&virt_to_page(page)->count); + clear_bit(PG_locked, &virt_to_page(page)->flags); + wake_up(&virt_to_page(page)->wait); free_page(page); return; } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/drm/i810_drv.c linux/drivers/char/drm/i810_drv.c --- v2.4.0-test5/linux/drivers/char/drm/i810_drv.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/drm/i810_drv.c Tue Aug 8 09:27:34 2000 @@ -32,8 +32,6 @@ #include #include "drmP.h" #include "i810_drv.h" -#include -#include #define I810_NAME "i810" #define I810_DESC "Intel I810" @@ -46,8 +44,8 @@ drm_ctx_t i810_res_ctx; static struct file_operations i810_fops = { -#if LINUX_VERSION_CODE >= 0x020322 - /* This started being used approx. 2.3.34 */ +#if LINUX_VERSION_CODE >= 0x020400 + /* This started being used during 2.4.0-test */ owner: THIS_MODULE, #endif open: i810_open, @@ -340,7 +338,7 @@ /* i810_init is called via init_module at module load time, or via * linux/init/main.c (this is not currently supported). */ -int i810_init(void) +static int i810_init(void) { int retcode; drm_device_t *dev = &i810_device; @@ -399,7 +397,7 @@ /* i810_cleanup is called via cleanup_module at module unload time. */ -void i810_cleanup(void) +static void i810_cleanup(void) { drm_device_t *dev = &i810_device; @@ -465,6 +463,9 @@ DRM_DEBUG("open_count = %d\n", dev->open_count); if (!(retcode = drm_open_helper(inode, filp, dev))) { +#if LINUX_VERSION_CODE < 0x020333 + MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */ +#endif atomic_inc(&dev->total_open); spin_lock(&dev->count_lock); if (!dev->open_count++) { @@ -545,6 +546,9 @@ up(&dev->struct_sem); drm_free(priv, sizeof(*priv), DRM_MEM_FILES); +#if LINUX_VERSION_CODE < 0x020333 + MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */ +#endif atomic_inc(&dev->total_close); spin_lock(&dev->count_lock); if (!--dev->open_count) { @@ -557,9 +561,10 @@ return -EBUSY; } spin_unlock(&dev->count_lock); - retcode = i810_takedown(dev); - } else - spin_unlock(&dev->count_lock); + unlock_kernel(); + return i810_takedown(dev); + } + spin_unlock(&dev->count_lock); unlock_kernel(); return retcode; } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/drm/memory.c linux/drivers/char/drm/memory.c --- v2.4.0-test5/linux/drivers/char/drm/memory.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/drm/memory.c Tue Aug 8 09:27:34 2000 @@ -30,7 +30,9 @@ */ #define __NO_VERSION__ +#include #include "drmP.h" +#include typedef struct drm_mem_stats { const char *name; @@ -245,7 +247,12 @@ for (addr = address, sz = bytes; sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { +#if LINUX_VERSION_CODE >= 0x020400 + /* Argument type changed in 2.4.0-test6/pre8 */ + mem_map_reserve(virt_to_page(addr)); +#else mem_map_reserve(MAP_NR(addr)); +#endif } return address; @@ -266,7 +273,12 @@ for (addr = address, sz = bytes; sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { +#if LINUX_VERSION_CODE >= 0x020400 + /* Argument type changed in 2.4.0-test6/pre8 */ + mem_map_unreserve(virt_to_page(addr)); +#else mem_map_unreserve(MAP_NR(addr)); +#endif } free_pages(address, order); } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/drm/mga_context.c linux/drivers/char/drm/mga_context.c --- v2.4.0-test5/linux/drivers/char/drm/mga_context.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/drm/mga_context.c Thu Aug 3 17:19:01 2000 @@ -29,8 +29,6 @@ * */ -#include - #define __NO_VERSION__ #include "drmP.h" #include "mga_drv.h" diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/drm/mga_dma.c linux/drivers/char/drm/mga_dma.c --- v2.4.0-test5/linux/drivers/char/drm/mga_dma.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/drm/mga_dma.c Mon Aug 7 21:01:36 2000 @@ -57,8 +57,8 @@ if(address == 0UL) { return 0; } - atomic_inc(&mem_map[MAP_NR((void *) address)].count); - set_bit(PG_locked, &mem_map[MAP_NR((void *) address)].flags); + atomic_inc(&virt_to_page(address)->count); + set_bit(PG_locked, &virt_to_page(address)->flags); return address; } @@ -70,9 +70,9 @@ if(page == 0UL) { return; } - atomic_dec(&mem_map[MAP_NR((void *) page)].count); - clear_bit(PG_locked, &mem_map[MAP_NR((void *) page)].flags); - wake_up(&mem_map[MAP_NR((void *) page)].wait); + atomic_dec(&virt_to_page(page)->count); + clear_bit(PG_locked, &virt_to_page(page)->flags); + wake_up(&virt_to_page(page)->wait); free_page(page); return; } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/drm/mga_drv.c linux/drivers/char/drm/mga_drv.c --- v2.4.0-test5/linux/drivers/char/drm/mga_drv.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/drm/mga_drv.c Tue Aug 8 09:27:34 2000 @@ -33,8 +33,6 @@ #include #include "drmP.h" #include "mga_drv.h" -#include -#include #define MGA_NAME "mga" #define MGA_DESC "Matrox g200/g400" @@ -47,8 +45,8 @@ drm_ctx_t mga_res_ctx; static struct file_operations mga_fops = { -#if LINUX_VERSION_CODE >= 0x020322 - /* This started being used approx. 2.3.34 */ +#if LINUX_VERSION_CODE >= 0x020400 + /* This started being used during 2.4.0-test */ owner: THIS_MODULE, #endif open: mga_open, @@ -339,7 +337,7 @@ /* mga_init is called via init_module at module load time, or via * linux/init/main.c (this is not currently supported). */ -int mga_init(void) +static int mga_init(void) { int retcode; drm_device_t *dev = &mga_device; @@ -404,7 +402,7 @@ /* mga_cleanup is called via cleanup_module at module unload time. */ -void mga_cleanup(void) +static void mga_cleanup(void) { drm_device_t *dev = &mga_device; @@ -481,6 +479,9 @@ DRM_DEBUG("open_count = %d\n", dev->open_count); if (!(retcode = drm_open_helper(inode, filp, dev))) { +#if LINUX_VERSION_CODE < 0x020333 + MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */ +#endif atomic_inc(&dev->total_open); spin_lock(&dev->count_lock); if (!dev->open_count++) { @@ -561,6 +562,9 @@ up(&dev->struct_sem); drm_free(priv, sizeof(*priv), DRM_MEM_FILES); +#if LINUX_VERSION_CODE < 0x020333 + MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */ +#endif atomic_inc(&dev->total_close); spin_lock(&dev->count_lock); if (!--dev->open_count) { @@ -573,9 +577,10 @@ return -EBUSY; } spin_unlock(&dev->count_lock); - retcode = mga_takedown(dev); - } else - spin_unlock(&dev->count_lock); + unlock_kernel(); + return mga_takedown(dev); + } + spin_unlock(&dev->count_lock); unlock_kernel(); return retcode; } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/drm/r128_bufs.c linux/drivers/char/drm/r128_bufs.c --- v2.4.0-test5/linux/drivers/char/drm/r128_bufs.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/drm/r128_bufs.c Mon Jul 31 11:22:14 2000 @@ -31,6 +31,7 @@ */ #define __NO_VERSION__ +#include #include "drmP.h" #include "r128_drv.h" #include "linux/un.h" diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/drm/r128_context.c linux/drivers/char/drm/r128_context.c --- v2.4.0-test5/linux/drivers/char/drm/r128_context.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/drm/r128_context.c Thu Aug 3 17:19:01 2000 @@ -28,8 +28,6 @@ * */ -#include - #define __NO_VERSION__ #include "drmP.h" #include "r128_drv.h" @@ -38,10 +36,6 @@ static int r128_alloc_queue(drm_device_t *dev) { -#if 0 - static int context = 0; -#endif - return drm_ctxbitmap_next(dev); } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/drm/r128_drv.c linux/drivers/char/drm/r128_drv.c --- v2.4.0-test5/linux/drivers/char/drm/r128_drv.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/drm/r128_drv.c Tue Aug 8 09:27:34 2000 @@ -32,8 +32,6 @@ #include #include "drmP.h" #include "r128_drv.h" -#include -#include #define R128_NAME "r128" #define R128_DESC "ATI Rage 128" @@ -46,8 +44,8 @@ drm_ctx_t r128_res_ctx; static struct file_operations r128_fops = { -#if LINUX_VERSION_CODE >= 0x020322 - /* This started being used approx. 2.3.34 */ +#if LINUX_VERSION_CODE >= 0x020400 + /* This started being used during 2.4.0-test */ owner: THIS_MODULE, #endif open: r128_open, @@ -325,7 +323,7 @@ /* r128_init is called via init_module at module load time, or via * linux/init/main.c (this is not currently supported). */ -int r128_init(void) +static int r128_init(void) { int retcode; drm_device_t *dev = &r128_device; @@ -389,7 +387,7 @@ /* r128_cleanup is called via cleanup_module at module unload time. */ -void r128_cleanup(void) +static void r128_cleanup(void) { drm_device_t *dev = &r128_device; @@ -457,6 +455,9 @@ DRM_DEBUG("open_count = %d\n", dev->open_count); if (!(retcode = drm_open_helper(inode, filp, dev))) { +#if LINUX_VERSION_CODE < 0x020333 + MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */ +#endif atomic_inc(&dev->total_open); spin_lock(&dev->count_lock); if (!dev->open_count++) { @@ -466,8 +467,6 @@ spin_unlock(&dev->count_lock); } - unlock_kernel(); - return retcode; } @@ -478,10 +477,12 @@ int retcode = 0; lock_kernel(); - dev = priv->dev; + dev = priv->dev; DRM_DEBUG("open_count = %d\n", dev->open_count); if (!(retcode = drm_release(inode, filp))) { - MOD_DEC_USE_COUNT; +#if LINUX_VERSION_CODE < 0x020333 + MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */ +#endif atomic_inc(&dev->total_close); spin_lock(&dev->count_lock); if (!--dev->open_count) { @@ -494,10 +495,12 @@ return -EBUSY; } spin_unlock(&dev->count_lock); - retcode = r128_takedown(dev); - } else - spin_unlock(&dev->count_lock); + unlock_kernel(); + return r128_takedown(dev); + } + spin_unlock(&dev->count_lock); } + unlock_kernel(); return retcode; } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/drm/tdfx_context.c linux/drivers/char/drm/tdfx_context.c --- v2.4.0-test5/linux/drivers/char/drm/tdfx_context.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/drm/tdfx_context.c Thu Aug 3 17:19:01 2000 @@ -30,8 +30,6 @@ * */ -#include - #define __NO_VERSION__ #include "drmP.h" #include "tdfx_drv.h" diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/drm/tdfx_drv.c linux/drivers/char/drm/tdfx_drv.c --- v2.4.0-test5/linux/drivers/char/drm/tdfx_drv.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/drm/tdfx_drv.c Tue Aug 8 09:27:34 2000 @@ -31,8 +31,6 @@ */ #include -#include -#include #include "drmP.h" #include "tdfx_drv.h" @@ -47,8 +45,8 @@ drm_ctx_t tdfx_res_ctx; static struct file_operations tdfx_fops = { -#if LINUX_VERSION_CODE >= 0x020322 - /* This started being used approx. 2.3.34 */ +#if LINUX_VERSION_CODE >= 0x020400 + /* This started being used during 2.4.0-test */ owner: THIS_MODULE, #endif open: tdfx_open, @@ -300,7 +298,7 @@ /* tdfx_init is called via init_module at module load time, or via * linux/init/main.c (this is not currently supported). */ -int tdfx_init(void) +static int tdfx_init(void) { int retcode; drm_device_t *dev = &tdfx_device; @@ -348,7 +346,7 @@ /* tdfx_cleanup is called via cleanup_module at module unload time. */ -void tdfx_cleanup(void) +static void tdfx_cleanup(void) { drm_device_t *dev = &tdfx_device; @@ -416,6 +414,9 @@ DRM_DEBUG("open_count = %d\n", dev->open_count); if (!(retcode = drm_open_helper(inode, filp, dev))) { +#if LINUX_VERSION_CODE < 0x020333 + MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */ +#endif atomic_inc(&dev->total_open); spin_lock(&dev->count_lock); if (!dev->open_count++) { @@ -438,6 +439,9 @@ DRM_DEBUG("open_count = %d\n", dev->open_count); if (!(retcode = drm_release(inode, filp))) { +#if LINUX_VERSION_CODE < 0x020333 + MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */ +#endif atomic_inc(&dev->total_close); spin_lock(&dev->count_lock); if (!--dev->open_count) { @@ -446,9 +450,11 @@ atomic_read(&dev->ioctl_count), dev->blocked); spin_unlock(&dev->count_lock); + unlock_kernel(); return -EBUSY; } spin_unlock(&dev->count_lock); + unlock_kernel(); return tdfx_takedown(dev); } spin_unlock(&dev->count_lock); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/drm/vm.c linux/drivers/char/drm/vm.c --- v2.4.0-test5/linux/drivers/char/drm/vm.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/drm/vm.c Tue Aug 8 09:27:34 2000 @@ -31,8 +31,6 @@ #define __NO_VERSION__ #include "drmP.h" -#include -#include struct vm_operations_struct drm_vm_ops = { nopage: drm_vm_nopage, @@ -46,6 +44,12 @@ close: drm_vm_close, }; +struct vm_operations_struct drm_vm_shm_lock_ops = { + nopage: drm_vm_shm_nopage_lock, + open: drm_vm_open, + close: drm_vm_close, +}; + struct vm_operations_struct drm_vm_dma_ops = { nopage: drm_vm_dma_nopage, open: drm_vm_open, @@ -79,6 +83,40 @@ int write_access) #endif { +#if LINUX_VERSION_CODE >= 0x020300 + drm_map_t *map = (drm_map_t *)vma->vm_private_data; +#else + drm_map_t *map = (drm_map_t *)vma->vm_pte; +#endif + unsigned long physical; + unsigned long offset; + + if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */ + if (!map) return NOPAGE_OOM; /* Nothing allocated */ + + offset = address - vma->vm_start; + physical = (unsigned long)map->handle + offset; + atomic_inc(&virt_to_page(physical)->count); /* Dec. by kernel */ + + DRM_DEBUG("0x%08lx => 0x%08lx\n", address, physical); +#if LINUX_VERSION_CODE < 0x020317 + return physical; +#else + return virt_to_page(physical); +#endif +} + +#if LINUX_VERSION_CODE < 0x020317 +unsigned long drm_vm_shm_nopage_lock(struct vm_area_struct *vma, + unsigned long address, + int write_access) +#else + /* Return type changed in 2.3.23 */ +struct page *drm_vm_shm_nopage_lock(struct vm_area_struct *vma, + unsigned long address, + int write_access) +#endif +{ drm_file_t *priv = vma->vm_file->private_data; drm_device_t *dev = priv->dev; unsigned long physical; @@ -91,13 +129,13 @@ offset = address - vma->vm_start; page = offset >> PAGE_SHIFT; physical = (unsigned long)dev->lock.hw_lock + offset; - atomic_inc(&mem_map[MAP_NR(physical)].count); /* Dec. by kernel */ + atomic_inc(&virt_to_page(physical)->count); /* Dec. by kernel */ DRM_DEBUG("0x%08lx (page %lu) => 0x%08lx\n", address, page, physical); #if LINUX_VERSION_CODE < 0x020317 return physical; #else - return mem_map + MAP_NR(physical); + return virt_to_page(physical); #endif } @@ -126,13 +164,13 @@ offset = address - vma->vm_start; /* vm_[pg]off[set] should be 0 */ page = offset >> PAGE_SHIFT; physical = dma->pagelist[page] + (offset & (~PAGE_MASK)); - atomic_inc(&mem_map[MAP_NR(physical)].count); /* Dec. by kernel */ + atomic_inc(&virt_to_page(physical)->count); /* Dec. by kernel */ DRM_DEBUG("0x%08lx (page %lu) => 0x%08lx\n", address, page, physical); #if LINUX_VERSION_CODE < 0x020317 return physical; #else - return mem_map + MAP_NR(physical); + return virt_to_page(physical); #endif } @@ -147,6 +185,11 @@ DRM_DEBUG("0x%08lx,0x%08lx\n", vma->vm_start, vma->vm_end - vma->vm_start); atomic_inc(&dev->vma_count); +#if LINUX_VERSION_CODE < 0x020333 + /* The map can exist after the fd is closed. */ + MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */ +#endif + #if DRM_DEBUG_CODE vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS); @@ -171,6 +214,9 @@ DRM_DEBUG("0x%08lx,0x%08lx\n", vma->vm_start, vma->vm_end - vma->vm_start); +#if LINUX_VERSION_CODE < 0x020333 + MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */ +#endif atomic_dec(&dev->vma_count); #if DRM_DEBUG_CODE @@ -292,7 +338,17 @@ vma->vm_ops = &drm_vm_ops; break; case _DRM_SHM: - vma->vm_ops = &drm_vm_shm_ops; + if (map->flags & _DRM_CONTAINS_LOCK) + vma->vm_ops = &drm_vm_shm_lock_ops; + else { + vma->vm_ops = &drm_vm_shm_ops; +#if LINUX_VERSION_CODE >= 0x020300 + vma->vm_private_data = (void *)map; +#else + vma->vm_pte = (unsigned long)map; +#endif + } + /* Don't let this area swap. Change when DRM_KERNEL advisory is supported. */ vma->vm_flags |= VM_LOCKED; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/ftape/lowlevel/ftape-buffer.c linux/drivers/char/ftape/lowlevel/ftape-buffer.c --- v2.4.0-test5/linux/drivers/char/ftape/lowlevel/ftape-buffer.c Wed Feb 16 17:03:51 2000 +++ linux/drivers/char/ftape/lowlevel/ftape-buffer.c Tue Aug 8 09:11:04 2000 @@ -48,11 +48,10 @@ } addr = __get_dma_pages(GFP_KERNEL, get_order(size)); if (addr) { - int i; + struct page *page; - for (i = MAP_NR(addr); i < MAP_NR(addr+size); i++) { - mem_map_reserve(i); - } + for (page = virt_to_page(addr); page < virt_to_page(addr+size); page++) + mem_map_reserve(page); } return (void *)addr; } @@ -60,12 +59,11 @@ static inline void dmafree(void *addr, size_t size) { if (size > 0) { - int i; + struct page *page; - for (i = MAP_NR((unsigned long)addr); - i < MAP_NR((unsigned long)addr+size); i++) { - mem_map_unreserve (i); - } + for (page = virt_to_page((unsigned long)addr); + page < virt_to_page((unsigned long)addr+size); page++) + mem_map_unreserve(page); free_pages((unsigned long) addr, get_order(size)); } } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/hp600_keyb.c linux/drivers/char/hp600_keyb.c --- v2.4.0-test5/linux/drivers/char/hp600_keyb.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/hp600_keyb.c Wed Aug 9 13:59:04 2000 @@ -5,7 +5,9 @@ */ #include +#include #include +#include #include #include "scan_keyb.h" @@ -23,7 +25,7 @@ 0x00, 0x00, 0x00, 0x2c, 0x00, 0x1c, 0x28, 0x35, 0x31, 0x30, 0x32, 0x33, 0x34, 0x2f, 0x2e, 0x2d, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x50, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x50, 0x7b, 0x38, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -46,25 +48,35 @@ }; +static const unsigned char hp690_switch[]= { + 0xfd, 0xff, + 0xdf, 0xff, + 0x7f, 0xff, + 0xff, 0xfe, + 0xff, 0xfd, + 0xff, 0xf7, + 0xff, 0xbf, + 0xff, 0x7f, +}; + + static void hp690_japanese_scan_kbd(unsigned char *s) { - ctrl_outb(0xfd, PDDR); ctrl_outb(0xff, PEDR); - *s++=ctrl_inb(PCDR); *s++=ctrl_inb(PFDR); - ctrl_outb(0xdf, PDDR); ctrl_outb(0xff, PEDR); - *s++=ctrl_inb(PCDR); *s++=ctrl_inb(PFDR); - ctrl_outb(0x7f, PDDR); ctrl_outb(0xff, PEDR); - *s++=ctrl_inb(PCDR); *s++=ctrl_inb(PFDR); - ctrl_outb(0xff, PDDR); ctrl_outb(0xfe, PEDR); - *s++=ctrl_inb(PCDR); *s++=ctrl_inb(PFDR); - ctrl_outb(0xff, PDDR); ctrl_outb(0xfd, PEDR); - *s++=ctrl_inb(PCDR); *s++=ctrl_inb(PFDR); - ctrl_outb(0xff, PDDR); ctrl_outb(0xf7, PEDR); - *s++=ctrl_inb(PCDR); *s++=ctrl_inb(PFDR); - ctrl_outb(0xff, PDDR); ctrl_outb(0xbf, PEDR); - *s++=ctrl_inb(PCDR); *s++=ctrl_inb(PFDR); - ctrl_outb(0xff, PDDR); ctrl_outb(0x7f, PEDR); - *s++=ctrl_inb(PCDR); *s++=ctrl_inb(PFDR); - *s++=ctrl_inb(PGDR); *s++=ctrl_inb(PHDR); + int i; + unsigned const char *t=hp690_switch; + + for(i=0; i<9; i++) { + ctrl_outb(*t++, PDDR); + ctrl_outb(*t++, PEDR); + *s++=ctrl_inb(PCDR); + *s++=ctrl_inb(PFDR); + } + + ctrl_outb(0xff, PDDR); + ctrl_outb(0xff, PEDR); + + *s++=ctrl_inb(PGDR); + *s++=ctrl_inb(PHDR); } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/joystick/Makefile linux/drivers/char/joystick/Makefile --- v2.4.0-test5/linux/drivers/char/joystick/Makefile Fri Jun 23 21:55:08 2000 +++ linux/drivers/char/joystick/Makefile Sun Aug 6 11:23:40 2000 @@ -14,7 +14,6 @@ O_TARGET := js.o M_OBJS := O_OBJS := -#MOD_LIST_NAME := INPUT_MODULES # Objects that export symbols. diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c --- v2.4.0-test5/linux/drivers/char/keyboard.c Wed Feb 16 17:03:52 2000 +++ linux/drivers/char/keyboard.c Mon Jul 31 19:36:10 2000 @@ -158,7 +158,6 @@ #ifdef CONFIG_MAGIC_SYSRQ static int sysrq_pressed; -int sysrq_enabled = 1; #endif static struct pm_dev *pm_kbd = NULL; @@ -255,7 +254,7 @@ sysrq_pressed = !up_flag; return; } else if (sysrq_pressed) { - if (!up_flag && sysrq_enabled) { + if (!up_flag) { handle_sysrq(kbd_sysrq_xlate[keycode], kbd_pt_regs, kbd, tty); return; } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/msp3400.c linux/drivers/char/msp3400.c --- v2.4.0-test5/linux/drivers/char/msp3400.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/msp3400.c Sun Aug 6 12:45:28 2000 @@ -1168,7 +1168,8 @@ if (simple == -1) { /* default mode */ - msp->simple = (((rev2>>8)&0xff) == 0) ? 0 : 1; + /* msp->simple = (((rev2>>8)&0xff) == 0) ? 0 : 1; */ + msp->simple = ((rev1&0xff)+'@' > 'C'); } else { /* use insmod option */ msp->simple = simple; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/n_tty.c linux/drivers/char/n_tty.c --- v2.4.0-test5/linux/drivers/char/n_tty.c Mon Jul 10 16:47:22 2000 +++ linux/drivers/char/n_tty.c Mon Jul 31 10:14:07 2000 @@ -1154,9 +1154,7 @@ nr -= num; if (nr == 0) break; - current->state = TASK_RUNNING; get_user(c, b); - current->state = TASK_INTERRUPTIBLE; if (opost(c, tty) < 0) break; b++; nr--; @@ -1164,9 +1162,7 @@ if (tty->driver.flush_chars) tty->driver.flush_chars(tty); } else { - current->state = TASK_RUNNING; c = tty->driver.write(tty, 1, b, nr); - current->state = TASK_INTERRUPTIBLE; if (c < 0) { retval = c; goto break_out; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/pcmcia/Makefile linux/drivers/char/pcmcia/Makefile --- v2.4.0-test5/linux/drivers/char/pcmcia/Makefile Thu Nov 11 20:11:34 1999 +++ linux/drivers/char/pcmcia/Makefile Sun Aug 6 11:23:40 2000 @@ -9,7 +9,6 @@ ALL_SUB_DIRS := $(SUB_DIRS) O_TARGET := pcmcia_char.o -MOD_LIST_NAME := PCMCIA_CHAR_MODULES obj-y := obj-m := diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/planb.c linux/drivers/char/planb.c --- v2.4.0-test5/linux/drivers/char/planb.c Thu May 11 15:30:06 2000 +++ linux/drivers/char/planb.c Mon Aug 7 21:01:36 2000 @@ -136,13 +136,12 @@ |GFP_DMA, 0); if (!pb->rawbuf[i]) break; - set_bit(PG_reserved, &mem_map[MAP_NR(pb->rawbuf[i])].flags); + mem_map_reserve(virt_to_page(pb->rawbuf[i])); } if (i-- < npage) { printk(KERN_DEBUG "PlanB: init_grab: grab buffer not allocated\n"); for (; i > 0; i--) { - clear_bit(PG_reserved, - &mem_map[MAP_NR(pb->rawbuf[i])].flags); + mem_map_unreserve(virt_to_page(pb->rawbuf[i])); free_pages((unsigned long)pb->rawbuf[i], 0); } kfree(pb->rawbuf); @@ -435,8 +434,7 @@ } if(pb->rawbuf) { for (i = 0; i < pb->rawbuf_size; i++) { - clear_bit(PG_reserved, - &mem_map[MAP_NR(pb->rawbuf[i])].flags); + mem_map_unreserve(virt_to_page(pb->rawbuf[i])); free_pages((unsigned long)pb->rawbuf[i], 0); } kfree(pb->rawbuf); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/radio-typhoon.c linux/drivers/char/radio-typhoon.c --- v2.4.0-test5/linux/drivers/char/radio-typhoon.c Tue Nov 23 22:42:20 1999 +++ linux/drivers/char/radio-typhoon.c Fri Aug 4 18:36:46 2000 @@ -300,32 +300,26 @@ static int typhoon_get_info(char *buf, char **start, off_t offset, int len) { + char *out = buf; + #ifdef MODULE #define MODULEPROCSTRING "Driver loaded as a module" #else #define MODULEPROCSTRING "Driver compiled into kernel" #endif - #define LIMIT (PAGE_SIZE - 80) - - len = 0; - len += sprintf(buf + len, BANNER); - if (len > LIMIT) return len; - len += sprintf(buf + len, "Load type: " MODULEPROCSTRING "\n\n"); - if (len > LIMIT) return len; - len += sprintf(buf + len, "frequency = %lu kHz\n", + /* output must be kept under PAGE_SIZE */ + out += sprintf(out, BANNER); + out += sprintf(out, "Load type: " MODULEPROCSTRING "\n\n"); + out += sprintf(out, "frequency = %lu kHz\n", typhoon_unit.curfreq >> 4); - if (len > LIMIT) return len; - len += sprintf(buf + len, "volume = %d\n", typhoon_unit.curvol); - if (len > LIMIT) return len; - len += sprintf(buf + len, "mute = %s\n", typhoon_unit.muted ? + out += sprintf(out, "volume = %d\n", typhoon_unit.curvol); + out += sprintf(out, "mute = %s\n", typhoon_unit.muted ? "on" : "off"); - if (len > LIMIT) return len; - len += sprintf(buf + len, "iobase = 0x%x\n", typhoon_unit.iobase); - if (len > LIMIT) return len; - len += sprintf(buf + len, "mute frequency = %lu kHz\n", + out += sprintf(out, "iobase = 0x%x\n", typhoon_unit.iobase); + out += sprintf(out, "mute frequency = %lu kHz\n", typhoon_unit.mutefreq >> 4); - return len; + return out - buf; } #endif /* CONFIG_RADIO_TYPHOON_PROC_FS */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/scan_keyb.c linux/drivers/char/scan_keyb.c --- v2.4.0-test5/linux/drivers/char/scan_keyb.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/scan_keyb.c Wed Aug 9 13:59:04 2000 @@ -91,9 +91,9 @@ kbd->s0=kbd->s1=NULL; if((kbd->s0=kmalloc(length, GFP_KERNEL))==NULL) - goto error_out; + goto error_mem_free; if((kbd->s1=kmalloc(length, GFP_KERNEL))==NULL) - goto error_out; + goto error_mem_free; kbd->scan(kbd->s0); kbd->scan(kbd->s1); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/sh-sci.c linux/drivers/char/sh-sci.c --- v2.4.0-test5/linux/drivers/char/sh-sci.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/sh-sci.c Wed Aug 9 13:59:04 2000 @@ -60,8 +60,10 @@ static void sci_init_pins_sci(struct sci_port* port, unsigned int cflag); #ifndef SCI_ONLY static void sci_init_pins_scif(struct sci_port* port, unsigned int cflag); -#endif +#if defined(__sh3__) static void sci_init_pins_irda(struct sci_port* port, unsigned int cflag); +#endif +#endif static void sci_disable_tx_interrupts(void *ptr); static void sci_enable_tx_interrupts(void *ptr); static void sci_disable_rx_interrupts(void *ptr); @@ -106,6 +108,8 @@ restore_flags(flags); } +#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB + static void handle_error(struct sci_port *port) { /* Clear error flags */ sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); @@ -133,8 +137,6 @@ return c; } -#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB - /* Taken from sh-stub.c of GDB 4.18 */ static const char hexchars[] = "0123456789abcdef"; @@ -221,7 +223,7 @@ #if defined(SCIF_ONLY) || defined(SCI_AND_SCIF) #if defined(__sh3__) -/* For SH7709, SH7709A, SH7729 */ +/* For SH7707, SH7709, SH7709A, SH7729 */ static void sci_init_pins_scif(struct sci_port* port, unsigned int cflag) { unsigned int fcr_val = 0; @@ -328,7 +330,7 @@ t = BPS_38400; break; default: - printk(KERN_INFO "sci: unsupported baud rate: %d, use 115200 instead.\n", baud); + printk(KERN_INFO "sci: unsupported baud rate: %d, using 115200 instead.\n", baud); case 115200: t = BPS_115200; break; @@ -412,6 +414,17 @@ * the interrupt related routines * * ********************************************************************** */ +/* + * This routine is used by the interrupt handler to schedule + * processing in the software interrupt portion of the driver. + */ +static inline void sci_sched_event(struct sci_port *port, int event) +{ + port->event |= 1 << event; + queue_task(&port->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + static void sci_transmit_chars(struct sci_port *port) { int count, i; @@ -459,6 +472,8 @@ } sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); + port->icount.tx += count; + /* Update the kernel buffer end */ port->gs.xmit_tail = (port->gs.xmit_tail + count) & (SERIAL_XMIT_SIZE-1); @@ -467,12 +482,8 @@ port->gs.xmit_cnt -= count; } - if (port->gs.xmit_cnt <= port->gs.wakeup_chars) { - if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - port->gs.tty->ldisc.write_wakeup) - (port->gs.tty->ldisc.write_wakeup)(port->gs.tty); - wake_up_interruptible(&port->gs.tty->write_wait); - } + if (port->gs.xmit_cnt <= port->gs.wakeup_chars) + sci_sched_event(port, SCI_EVENT_WRITE_WAKEUP); save_and_cli(flags); ctrl = sci_in(port, SCSCR); @@ -530,6 +541,7 @@ tty->flip.flag_buf_ptr += count; copied += count; + port->icount.rx += count; } if (copied) @@ -572,6 +584,23 @@ sci_tx_interrupt(irq, ptr, regs); } +static void do_softint(void *private_) +{ + struct sci_port *port = (struct sci_port *) private_; + struct tty_struct *tty; + + tty = port->gs.tty; + if (!tty) + return; + + if (test_and_clear_bit(SCI_EVENT_WRITE_WAKEUP, &port->event)) { + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + wake_up_interruptible(&tty->write_wait); + } +} + /* ********************************************************************** * * Here are the routines that actually * * interface with the generic_serial driver * @@ -675,6 +704,10 @@ port->gs.tty = tty; port->gs.count++; + port->event = 0; + port->tqueue.routine = do_softint; + port->tqueue.data = port; + /* * Start up serial port */ @@ -841,9 +874,22 @@ len += sprintf(page, "sciinfo:0.1\n"); for (i = 0; i < SCI_NPORTS && len < 4000; i++) { port = &sci_ports[i]; - len += sprintf(page+len, "%d: uart:%s address: %08x\n", i, + len += sprintf(page+len, "%d: uart:%s address: %08x", i, (port->type == PORT_SCI) ? "SCI" : "SCIF", port->base); + len += sprintf(page+len, " baud:%d", port->gs.baud); + len += sprintf(page+len, " tx:%d rx:%d", + port->icount.tx, port->icount.rx); + + if (port->icount.frame) + len += sprintf(page+len, " fe:%d", port->icount.frame); + if (port->icount.parity) + len += sprintf(page+len, " pe:%d", port->icount.parity); + if (port->icount.brk) + len += sprintf(page+len, " brk:%d", port->icount.brk); + if (port->icount.overrun) + len += sprintf(page+len, " oe:%d", port->icount.overrun); + len += sprintf(page+len, "\n"); } return len; } @@ -923,6 +969,11 @@ init_waitqueue_head(&port->gs.open_wait); init_waitqueue_head(&port->gs.close_wait); port->old_cflag = 0; + port->icount.cts = port->icount.dsr = + port->icount.rng = port->icount.dcd = 0; + port->icount.rx = port->icount.tx = 0; + port->icount.frame = port->icount.parity = 0; + port->icount.overrun = port->icount.brk = 0; } return 0; @@ -943,8 +994,6 @@ printk("ttySC%d at 0x%08x is a %s\n", j, port->base, (port->type == PORT_SCI) ? "SCI" : "SCIF"); for (i=0; i<3; i++) { - set_ipr_data(port->irqs[i], port->intc_addr, port->intc_pos, SCI_PRIORITY); - if (request_irq(port->irqs[i], handlers[i], SA_INTERRUPT, "sci", port)) { printk(KERN_ERR "sci: Cannot allocate irq.\n"); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/sh-sci.h linux/drivers/char/sh-sci.h --- v2.4.0-test5/linux/drivers/char/sh-sci.h Thu Jul 27 17:38:00 2000 +++ linux/drivers/char/sh-sci.h Wed Aug 9 13:59:04 2000 @@ -20,11 +20,11 @@ #define SCIx_RXI_IRQ 1 #define SCIx_TXI_IRQ 2 -/* ERI, RXI, TXI, INTC reg, INTC pos */ -#define SCI_IRQS { 23, 24, 25 }, INTC_IPRB, 1 -#define SH3_SCIF_IRQS { 56, 57, 59 }, INTC_IPRE, 1 -#define SH3_IRDA_IRQS { 52, 53, 55 }, INTC_IPRE, 2 -#define SH4_SCIF_IRQS { 40, 41, 43 }, INTC_IPRC, 1 +/* ERI, RXI, TXI, */ +#define SCI_IRQS { 23, 24, 25 } +#define SH3_SCIF_IRQS { 56, 57, 59 } +#define SH3_IRDA_IRQS { 52, 53, 55 } +#define SH4_SCIF_IRQS { 40, 41, 43 } #if defined(CONFIG_CPU_SUBTYPE_SH7708) # define SCI_NPORTS 1 @@ -34,12 +34,12 @@ # define SCSPTR 0xffffff7c /* 8 bit */ # define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ # define SCI_ONLY -#elif defined(CONFIG_CPU_SUBTYPE_SH7709) +#elif defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) # define SCI_NPORTS 3 # define SCI_INIT { \ - { {}, PORT_SCI, 0xfffffe80, SCI_IRQS, sci_init_pins_sci }, \ - { {}, PORT_SCIF, 0xA4000150, SH3_SCIF_IRQS, sci_init_pins_scif }, \ - { {}, PORT_SCIF, 0xA4000140, SH3_IRDA_IRQS, sci_init_pins_irda } \ + { {}, PORT_SCI, 0xfffffe80, SCI_IRQS, sci_init_pins_sci }, \ + { {}, PORT_SCIF, 0xA4000150, SH3_SCIF_IRQS, sci_init_pins_scif }, \ + { {}, PORT_SCIF, 0xA4000140, SH3_IRDA_IRQS, sci_init_pins_irda } \ } # define SCPCR 0xA4000116 /* 16 bit SCI and SCIF */ # define SCPDR 0xA4000136 /* 8 bit SCI and SCIF */ @@ -68,32 +68,32 @@ #define SCI_CTRL_FLAGS_TE 0x20 /* all */ #define SCI_CTRL_FLAGS_RE 0x10 /* all */ /* SCI_CTRL_FLAGS_REIE 0x08 * 7750 SCIF */ -/* SCI_CTRL_FLAGS_MPIE 0x08 * 7708 SCI, 7709 SCI, 7750 SCI */ -/* SCI_CTRL_FLAGS_TEIE 0x04 * 7708 SCI, 7709 SCI, 7750 SCI */ +/* SCI_CTRL_FLAGS_MPIE 0x08 * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ +/* SCI_CTRL_FLAGS_TEIE 0x04 * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ /* SCI_CTRL_FLAGS_CKE1 0x02 * all */ -/* SCI_CTRL_FLAGS_CKE0 0x01 * 7708 SCI, 7709 SCI/SCIF, 7750 SCI */ +/* SCI_CTRL_FLAGS_CKE0 0x01 * 7707 SCI/SCIF, 7708 SCI, 7709 SCI/SCIF, 7750 SCI */ /* SCxSR SCI */ -#define SCI_TDRE 0x80 /* 7708 SCI, 7709 SCI, 7750 SCI */ -#define SCI_RDRF 0x40 /* 7708 SCI, 7709 SCI, 7750 SCI */ -#define SCI_ORER 0x20 /* 7708 SCI, 7709 SCI, 7750 SCI */ -#define SCI_FER 0x10 /* 7708 SCI, 7709 SCI, 7750 SCI */ -#define SCI_PER 0x08 /* 7708 SCI, 7709 SCI, 7750 SCI */ -#define SCI_TEND 0x04 /* 7708 SCI, 7709 SCI, 7750 SCI */ -/* SCI_MPB 0x02 * 7708 SCI, 7709 SCI, 7750 SCI */ -/* SCI_MPBT 0x01 * 7708 SCI, 7709 SCI, 7750 SCI */ +#define SCI_TDRE 0x80 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ +#define SCI_RDRF 0x40 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ +#define SCI_ORER 0x20 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ +#define SCI_FER 0x10 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ +#define SCI_PER 0x08 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ +#define SCI_TEND 0x04 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ +/* SCI_MPB 0x02 * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ +/* SCI_MPBT 0x01 * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ #define SCI_ERRORS ( SCI_PER | SCI_FER | SCI_ORER) /* SCxSR SCIF */ -#define SCIF_ER 0x0080 /* 7709 SCIF, 7750 SCIF */ -#define SCIF_TEND 0x0040 /* 7709 SCIF, 7750 SCIF */ -#define SCIF_TDFE 0x0020 /* 7709 SCIF, 7750 SCIF */ -#define SCIF_BRK 0x0010 /* 7709 SCIF, 7750 SCIF */ -#define SCIF_FER 0x0008 /* 7709 SCIF, 7750 SCIF */ -#define SCIF_PER 0x0004 /* 7709 SCIF, 7750 SCIF */ -#define SCIF_RDF 0x0002 /* 7709 SCIF, 7750 SCIF */ -#define SCIF_DR 0x0001 /* 7709 SCIF, 7750 SCIF */ +#define SCIF_ER 0x0080 /* 7707 SCIF, 7709 SCIF, 7750 SCIF */ +#define SCIF_TEND 0x0040 /* 7707 SCIF, 7709 SCIF, 7750 SCIF */ +#define SCIF_TDFE 0x0020 /* 7707 SCIF, 7709 SCIF, 7750 SCIF */ +#define SCIF_BRK 0x0010 /* 7707 SCIF, 7709 SCIF, 7750 SCIF */ +#define SCIF_FER 0x0008 /* 7707 SCIF, 7709 SCIF, 7750 SCIF */ +#define SCIF_PER 0x0004 /* 7707 SCIF, 7709 SCIF, 7750 SCIF */ +#define SCIF_RDF 0x0002 /* 7707 SCIF, 7709 SCIF, 7750 SCIF */ +#define SCIF_DR 0x0001 /* 7707 SCIF, 7709 SCIF, 7750 SCIF */ #define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK) @@ -128,8 +128,6 @@ #define SCFCR_TFRST 0x0004 #define SCFCR_MCE 0x0008 -#define SCI_PRIORITY 3 - #define SCI_MAJOR 204 #define SCI_MINOR_START 8 @@ -161,14 +159,22 @@ #define SCI_MAGIC 0xbabeface +/* + * Events are used to schedule things to happen at timer-interrupt + * time, instead of at rs interrupt time. + */ +#define SCI_EVENT_WRITE_WAKEUP 0 + struct sci_port { struct gs_port gs; int type; unsigned int base; unsigned char irqs[3]; /* ERI, RXI, TXI */ - unsigned int intc_addr, intc_pos; void (*init_pins)(struct sci_port* port, unsigned int cflag); unsigned int old_cflag; + struct async_icount icount; + struct tq_struct tqueue; + unsigned long event; }; #define SCI_IN(size, offset) \ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/sysrq.c linux/drivers/char/sysrq.c --- v2.4.0-test5/linux/drivers/char/sysrq.c Mon Mar 27 08:08:24 2000 +++ linux/drivers/char/sysrq.c Mon Jul 31 19:36:10 2000 @@ -30,6 +30,9 @@ extern int console_loglevel; extern struct list_head super_blocks; +/* Whether we react on sysrq keys or just ignore them */ +int sysrq_enabled = 1; + /* Machine specific power off function */ void (*sysrq_power_off)(void) = NULL; @@ -59,6 +62,9 @@ struct kbd_struct *kbd, struct tty_struct *tty) { int orig_log_level = console_loglevel; + + if (!sysrq_enabled) + return; if (!key) return; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/tda9875.c linux/drivers/char/tda9875.c --- v2.4.0-test5/linux/drivers/char/tda9875.c Tue May 23 15:31:34 2000 +++ linux/drivers/char/tda9875.c Sun Aug 6 12:45:28 2000 @@ -5,7 +5,7 @@ * This driver will not complain if used with any * other i2c device with the same address. * - * Copyright (c) 2000 Guillamue Delvit based on Gerd Knorr source and + * Copyright (c) 2000 Guillaume Delvit based on Gerd Knorr source and * Eric Sandeen * This code is placed under the terms of the GNU General Public License * Based on tda9855.c by Steve VanDeBogart (vandebo@uclink.berkeley.edu) @@ -121,7 +121,7 @@ /* Begin code */ -static int tda9875_write(struct i2c_client *client, int subaddr, int val) +static int tda9875_write(struct i2c_client *client, int subaddr, unsigned char val) { unsigned char buffer[2]; dprintk("In tda9875_write\n"); @@ -153,12 +153,19 @@ static void tda9875_set(struct i2c_client *client) { struct tda9875 *tda = client->data; - + unsigned char a; + dprintk(KERN_DEBUG "tda9875_set(%04x,%04x,%04x,%04x)\n",tda->lvol,tda->rvol,tda->bass,tda->treble); - tda9875_write(client, TDA9875_MVL, tda->lvol / 600 - 84); - tda9875_write(client, TDA9875_MVR, tda->rvol / 600 -84); - tda9875_write(client, TDA9875_MBA, tda->bass / 2340 -12); - tda9875_write(client, TDA9875_MTR, tda->treble / 2621 -12); + + + a = tda->lvol & 0xff; + tda9875_write(client, TDA9875_MVL, a); + a =tda->rvol & 0xff; + tda9875_write(client, TDA9875_MVR, a); + a =tda->bass & 0xff; + tda9875_write(client, TDA9875_MBA, a); + a =tda->treble & 0xff; + tda9875_write(client, TDA9875_MTR, a); } static void do_tda9875_init(struct i2c_client *client) @@ -198,10 +205,10 @@ tda9875_write(client, TDA9875_MUT, 0xcc ); /* General mute */ - t->mode=AUDIO_MUTE; - t->lvol=t->rvol =51000; /* 0dB */ - t->bass=30420; /* 0dB */ - t->treble=34073; /* 0dB */ + t->mode=AUDIO_UNMUTE; + t->lvol=t->rvol =0; /* 0dB */ + t->bass=0; /* 0dB */ + t->treble=0; /* 0dB */ tda9875_set(client); } @@ -280,15 +287,15 @@ VIDEO_AUDIO_TREBLE; /* min is -84 max is 24 */ - left = (t->lvol+85)*600; - right = (t->rvol+85)*600; + left = (t->lvol+84)*606; + right = (t->rvol+84)*606; va->volume=MAX(left,right); va->balance=(32768*MIN(left,right))/ (va->volume ? va->volume : 1); va->balance=(leftbalance) : va->balance; - va->bass = (t->bass+13)*2340; /* min -12 max +15 */ - va->treble = (t->treble+13)*2621;/* min -12 max +12 */ + va->bass = (t->bass+12)*2427; /* min -12 max +15 */ + va->treble = (t->treble+12)*2730;/* min -12 max +12 */ va->mode |= VIDEO_SOUND_MONO; @@ -306,11 +313,36 @@ va->volume) / 32768; right = (MIN(va->balance,32768) * va->volume) / 32768; - t->lvol = left/600-84; - t->rvol = right/600-84; - t->bass = va->bass/2340-12; - t->treble = va->treble/2621-12; - tda9875_set(client); + t->lvol = ((left/606)-84) & 0xff; + if (t->lvol > 24) + t->lvol = 24; + if (t->lvol < -84) + t->lvol = -84 & 0xff; + + t->rvol = ((right/606)-84) & 0xff; + if (t->rvol > 24) + t->rvol = 24; + if (t->rvol < -84) + t->rvol = -84 & 0xff; + + t->bass = ((va->bass/2400)-12) & 0xff; + if (t->bass > 15) + t->bass = 15; + if (t->bass < -12) + t->bass = -12 & 0xff; + + t->treble = ((va->treble/2700)-12) & 0xff; + if (t->treble > 12) + t->treble = 12; + if (t->treble < -12) + t->treble = -12 & 0xff; + + + +//printk("tda9875 bal:%04x vol:%04x bass:%04x treble:%04x\n",va->balance,va->volume,va->bass,va->treble); + + + tda9875_set(client); break; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/char/zr36120_mem.c linux/drivers/char/zr36120_mem.c --- v2.4.0-test5/linux/drivers/char/zr36120_mem.c Wed Feb 16 17:03:52 2000 +++ linux/drivers/char/zr36120_mem.c Mon Aug 7 21:01:36 2000 @@ -50,7 +50,7 @@ if (mem) { unsigned long adr = (unsigned long)mem; while (size > 0) { - mem_map_reserve(MAP_NR(phys_to_virt(adr))); + mem_map_reserve(virt_to_page(phys_to_virt(adr))); adr += PAGE_SIZE; size -= PAGE_SIZE; } @@ -64,7 +64,7 @@ unsigned long adr = (unsigned long)mem; unsigned long siz = size; while (siz > 0) { - mem_map_unreserve(MAP_NR(phys_to_virt(adr))); + mem_map_unreserve(virt_to_page(phys_to_virt(adr))); adr += PAGE_SIZE; siz -= PAGE_SIZE; } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/fc4/Makefile linux/drivers/fc4/Makefile --- v2.4.0-test5/linux/drivers/fc4/Makefile Fri Jan 21 18:19:16 2000 +++ linux/drivers/fc4/Makefile Sun Aug 6 11:23:40 2000 @@ -5,7 +5,6 @@ L_TARGET := fc4.a M_OBJS := -MOD_LIST_NAME := FC4_MODULES ifeq ($(CONFIG_FC4),y) FC4 = fc.o diff -u --recursive --new-file v2.4.0-test5/linux/drivers/i2c/Config.in linux/drivers/i2c/Config.in --- v2.4.0-test5/linux/drivers/i2c/Config.in Tue Feb 1 01:35:43 2000 +++ linux/drivers/i2c/Config.in Mon Jul 31 10:21:58 2000 @@ -10,7 +10,7 @@ dep_tristate 'I2C bit-banging interfaces' CONFIG_I2C_ALGOBIT $CONFIG_I2C if [ "$CONFIG_I2C_ALGOBIT" != "n" ]; then - dep_tristate ' Philips style parallel port adapter' CONFIG_I2C_PHILIPSPAR $CONFIG_I2C_ALGOBIT + dep_tristate ' Philips style parallel port adapter' CONFIG_I2C_PHILIPSPAR $CONFIG_I2C_ALGOBIT $CONFIG_PARPORT dep_tristate ' ELV adapter' CONFIG_I2C_ELV $CONFIG_I2C_ALGOBIT dep_tristate ' Velleman K9000 adapter' CONFIG_I2C_VELLEMAN $CONFIG_I2C_ALGOBIT fi diff -u --recursive --new-file v2.4.0-test5/linux/drivers/i2c/Makefile linux/drivers/i2c/Makefile --- v2.4.0-test5/linux/drivers/i2c/Makefile Fri Jun 23 21:55:08 2000 +++ linux/drivers/i2c/Makefile Sun Aug 6 11:23:40 2000 @@ -2,7 +2,6 @@ # Makefile for the kernel i2c bus driver. # -MOD_LIST_NAME := I2C_MODULES O_TARGET := i2c.o export-objs := i2c-core.o i2c-algo-bit.o i2c-algo-pcf.o diff -u --recursive --new-file v2.4.0-test5/linux/drivers/ide/Makefile linux/drivers/ide/Makefile --- v2.4.0-test5/linux/drivers/ide/Makefile Fri Jun 23 21:55:08 2000 +++ linux/drivers/ide/Makefile Sun Aug 6 11:23:40 2000 @@ -21,7 +21,6 @@ O_TARGET := idedriver.o O_OBJS := ide-geometry.o M_OBJS := -MOD_LIST_NAME := IDE_MODULES OX_OBJS := MX_OBJS := diff -u --recursive --new-file v2.4.0-test5/linux/drivers/ide/ide-features.c linux/drivers/ide/ide-features.c --- v2.4.0-test5/linux/drivers/ide/ide-features.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/ide/ide-features.c Thu Aug 3 16:07:42 2000 @@ -164,10 +164,8 @@ * change (copied from ide-probe.c) */ struct hd_driveid *id; - unsigned long timeout, irqs, flags; + unsigned long timeout, flags; - probe_irq_off(probe_irq_on()); - irqs = probe_irq_on(); SELECT_MASK(HWIF(drive), drive, 1); if (IDE_CONTROL_REG) OUT_BYTE(drive->ctl,IDE_CONTROL_REG); @@ -176,8 +174,6 @@ timeout = jiffies + WAIT_WORSTCASE; do { if (0 < (signed long)(jiffies - timeout)) { - if (irqs) - (void) probe_irq_off(irqs); SELECT_MASK(HWIF(drive), drive, 0); return 0; /* drive timed-out */ } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/ide/ide-geometry.c linux/drivers/ide/ide-geometry.c --- v2.4.0-test5/linux/drivers/ide/ide-geometry.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/ide/ide-geometry.c Sun Aug 6 11:30:07 2000 @@ -2,15 +2,9 @@ * linux/drivers/ide/ide-geometry.c */ #include - -#if defined(CONFIG_IDE) && !defined(CONFIG_BLK_DEV_HD_ONLY) #include - #include -extern ide_drive_t * get_info_ptr(kdev_t); -extern unsigned long current_capacity (ide_drive_t *); - /* * We query CMOS about hard disks : it could be that we have a SCSI/ESDI/etc * controller that is BIOS compatible with ST-506, and thus showing up in our @@ -42,7 +36,7 @@ * The code below is bad. One of the problems is that drives 1 and 2 * may be SCSI disks (even when IDE disks are present), so that * the geometry we read here from BIOS is attributed to the wrong disks. - * Consequently, also the "drive->present = 1" below is a mistake. + * Consequently, also the former "drive->present = 1" below was a mistake. * * Eventually the entire routine below should be removed. */ @@ -74,7 +68,8 @@ drive->sect = drive->bios_sect = sect; drive->ctl = *(BIOS+8); } else { - printk("hd%d: C/H/S=%d/%d/%d from BIOS ignored\n", unit, cyl, head, sect); + printk("hd%d: C/H/S=%d/%d/%d from BIOS ignored\n", + unit, cyl, head, sect); } } @@ -84,6 +79,11 @@ } +#ifdef CONFIG_BLK_DEV_IDE + +extern ide_drive_t * get_info_ptr(kdev_t); +extern unsigned long current_capacity (ide_drive_t *); + /* * If heads is nonzero: find a translation with this many heads and S=63. * Otherwise: find out how OnTrack Disk Manager would translate the disk. @@ -211,4 +211,4 @@ drive->bios_cyl, drive->bios_head, drive->bios_sect); return ret; } -#endif /* (CONFIG_IDE) && !(CONFIG_BLK_DEV_HD_ONLY) */ +#endif /* CONFIG_BLK_DEV_IDE */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/ide/ide-probe.c linux/drivers/ide/ide-probe.c --- v2.4.0-test5/linux/drivers/ide/ide-probe.c Mon Jul 10 16:47:23 2000 +++ linux/drivers/ide/ide-probe.c Thu Aug 3 16:29:49 2000 @@ -184,22 +184,16 @@ * 1 device timed-out (no response to identify request) * 2 device aborted the command (refused to identify itself) */ -static int try_to_identify (ide_drive_t *drive, byte cmd) +static int actual_try_to_identify (ide_drive_t *drive, byte cmd) { int rc; ide_ioreg_t hd_status; unsigned long timeout; - unsigned long irqs = 0; byte s, a; if (IDE_CONTROL_REG) { - if (!HWIF(drive)->irq) { /* already got an IRQ? */ - probe_irq_off(probe_irq_on()); /* clear dangling irqs */ - irqs = probe_irq_on(); /* start monitoring irqs */ - OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* enable device irq */ - } - - ide_delay_50ms(); /* take a deep breath */ + /* take a deep breath */ + ide_delay_50ms(); a = IN_BYTE(IDE_ALTSTATUS_REG); s = IN_BYTE(IDE_STATUS_REG); if ((a ^ s) & ~INDEX_STAT) { @@ -222,8 +216,6 @@ /* DC4030 hosted drives need their own identify... */ extern int pdc4030_identify(ide_drive_t *); if (pdc4030_identify(drive)) { - if (irqs) - (void) probe_irq_off(irqs); return 1; } } else @@ -233,8 +225,6 @@ timeout += jiffies; do { if (0 < (signed long)(jiffies - timeout)) { - if (irqs) - (void) probe_irq_off(irqs); return 1; /* drive timed-out */ } ide_delay_50ms(); /* give drive a breather */ @@ -251,31 +241,48 @@ __restore_flags(flags); /* local CPU only */ } else rc = 2; /* drive refused ID */ + return rc; +} + +static int try_to_identify (ide_drive_t *drive, byte cmd) +{ + int retval; + int autoprobe = 0; + unsigned long cookie = 0; + if (IDE_CONTROL_REG && !HWIF(drive)->irq) { - irqs = probe_irq_off(irqs); /* get our irq number */ - if (irqs > 0) { - HWIF(drive)->irq = irqs; /* save it for later */ - irqs = probe_irq_on(); - OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* mask device irq */ - udelay(5); - (void) probe_irq_off(irqs); - (void) probe_irq_off(probe_irq_on()); /* clear self-inflicted irq */ - (void) GET_STAT(); /* clear drive IRQ */ + autoprobe = 1; + cookie = probe_irq_on(); + OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* enable device irq */ + } + + retval = actual_try_to_identify(drive, cmd); - } else { /* Mmmm.. multiple IRQs.. don't know which was ours */ - printk("%s: IRQ probe failed (%ld)\n", drive->name, irqs); + if (autoprobe) { + int irq; + OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* mask device irq */ + (void) GET_STAT(); /* clear drive IRQ */ + udelay(5); + irq = probe_irq_off(cookie); + if (!HWIF(drive)->irq) { + if (irq > 0) { + HWIF(drive)->irq = irq; + } else { /* Mmmm.. multiple IRQs.. don't know which was ours */ + printk("%s: IRQ probe failed (0x%lx)\n", drive->name, cookie); #ifdef CONFIG_BLK_DEV_CMD640 #ifdef CMD640_DUMP_REGS - if (HWIF(drive)->chipset == ide_cmd640) { - printk("%s: Hmmm.. probably a driver problem.\n", drive->name); - CMD640_DUMP_REGS; - } + if (HWIF(drive)->chipset == ide_cmd640) { + printk("%s: Hmmm.. probably a driver problem.\n", drive->name); + CMD640_DUMP_REGS; + } #endif /* CMD640_DUMP_REGS */ #endif /* CONFIG_BLK_DEV_CMD640 */ + } } } - return rc; + return retval; } + /* * do_probe() has the difficult job of finding a drive if it exists, diff -u --recursive --new-file v2.4.0-test5/linux/drivers/ide/pdc202xx.c linux/drivers/ide/pdc202xx.c --- v2.4.0-test5/linux/drivers/ide/pdc202xx.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/ide/pdc202xx.c Fri Jul 28 12:08:30 2000 @@ -862,7 +862,6 @@ (hwif->pci_dev->device == PCI_DEVICE_ID_PROMISE_20265) || (hwif->pci_dev->device == PCI_DEVICE_ID_PROMISE_20267)) { hwif->resetproc = &pdc202xx_reset; - hwif->tri_proc = &pdc202xx_tristate; } #ifdef CONFIG_BLK_DEV_IDEDMA diff -u --recursive --new-file v2.4.0-test5/linux/drivers/ieee1394/Makefile linux/drivers/ieee1394/Makefile --- v2.4.0-test5/linux/drivers/ieee1394/Makefile Mon Jul 10 16:47:23 2000 +++ linux/drivers/ieee1394/Makefile Sun Aug 6 11:23:40 2000 @@ -12,8 +12,6 @@ MOD_SUB_DIRS := $(SUB_DIRS) ALL_SUB_DIRS := $(SUB_DIRS) -MOD_LIST_NAME := IEEE1394_MODULES - L_TARGET := ieee1394.a L_OBJS := LX_OBJS := diff -u --recursive --new-file v2.4.0-test5/linux/drivers/ieee1394/video1394.c linux/drivers/ieee1394/video1394.c --- v2.4.0-test5/linux/drivers/ieee1394/video1394.c Fri Jul 14 12:12:09 2000 +++ linux/drivers/ieee1394/video1394.c Mon Aug 7 21:01:36 2000 @@ -144,7 +144,7 @@ */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -#define page_address(x) (x) +#define page_address(x) ((void *) (x)) #endif /* Given PGD from the address space's page table, return the kernel @@ -161,9 +161,10 @@ if (!pmd_none(*pmd)) { ptep = pte_offset(pmd, adr); pte = *ptep; - if(pte_present(pte)) - ret = (page_address(pte_page(pte))| - (adr&(PAGE_SIZE-1))); + if(pte_present(pte)) { + ret = (unsigned long) page_address(pte_page(pte)); + ret |= (adr & (PAGE_SIZE - 1)); + } } } MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret)); @@ -220,7 +221,7 @@ while (size > 0) { page = kvirt_to_pa(adr); - mem_map_reserve(MAP_NR(__va(page))); + mem_map_reserve(virt_to_page(__va(page))); adr+=PAGE_SIZE; size-=PAGE_SIZE; } @@ -238,7 +239,7 @@ while (size > 0) { page = kvirt_to_pa(adr); - mem_map_unreserve(MAP_NR(__va(page))); + mem_map_unreserve(virt_to_page(__va(page))); adr+=PAGE_SIZE; size-=PAGE_SIZE; } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/amd7930.c linux/drivers/isdn/hisax/amd7930.c --- v2.4.0-test5/linux/drivers/isdn/hisax/amd7930.c Thu Nov 11 20:11:37 1999 +++ linux/drivers/isdn/hisax/amd7930.c Sun Aug 6 12:43:41 2000 @@ -1,25 +1,9 @@ -/* $Id: amd7930.c,v 1.3 1999/07/12 21:04:52 keil Exp $ +/* $Id: amd7930.c,v 1.4 2000/06/26 08:59:12 keil Exp $ * * HiSax ISDN driver - chip specific routines for AMD 7930 * * Author Brent Baccala (baccala@FreeSoft.org) * - * - * - * $Log: amd7930.c,v $ - * Revision 1.3 1999/07/12 21:04:52 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 1.2 1998/02/12 23:07:10 keil - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 1.1 1998/02/03 23:20:51 keil - * New files for SPARC isdn support - * - * Revision 1.1 1998/01/08 04:17:12 baccala - * ISDN comes to the Sparc. Key points: - * * - Existing ISDN HiSax driver provides all the smarts * - it compiles, runs, talks to an isolated phone switch, connects * to a Cisco, pings go through @@ -30,6 +14,7 @@ * * The code is unreliable enough to be consider alpha * + * This file is (c) under GNU PUBLIC LICENSE * * Advanced Micro Devices' Am79C30A is an ISDN/audio chip used in the * SparcStation 1+. The chip provides microphone and speaker interfaces @@ -109,7 +94,7 @@ #include "rawhdlc.h" #include -static const char *amd7930_revision = "$Revision: 1.3 $"; +static const char *amd7930_revision = "$Revision: 1.4 $"; #define RCV_BUFSIZE 1024 /* Size of raw receive buffer in bytes */ #define RCV_BUFBLKS 4 /* Number of blocks to divide buffer into diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/arcofi.c linux/drivers/isdn/hisax/arcofi.c --- v2.4.0-test5/linux/drivers/isdn/hisax/arcofi.c Wed Feb 16 17:03:52 2000 +++ linux/drivers/isdn/hisax/arcofi.c Sun Aug 6 12:43:41 2000 @@ -1,43 +1,10 @@ -/* $Id: arcofi.c,v 1.10 1999/12/23 15:09:32 keil Exp $ - +/* $Id: arcofi.c,v 1.11 2000/06/26 08:59:12 keil Exp $ + * * arcofi.c Ansteuerung ARCOFI 2165 * * Author Karsten Keil (keil@isdn4linux.de) * - * - * - * $Log: arcofi.c,v $ - * Revision 1.10 1999/12/23 15:09:32 keil - * change email - * - * Revision 1.9 1999/12/19 13:09:41 keil - * changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for - * signal proof delays - * - * Revision 1.8 1999/08/25 16:50:51 keil - * Fix bugs which cause 2.3.14 hangs (waitqueue init) - * - * Revision 1.7 1999/07/01 08:11:17 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 1.6 1998/09/30 22:21:56 keil - * cosmetics - * - * Revision 1.5 1998/09/27 12:52:57 keil - * cosmetics - * - * Revision 1.4 1998/08/20 13:50:24 keil - * More support for hybrid modem (not working yet) - * - * Revision 1.3 1998/05/25 12:57:38 keil - * HiSax golden code from certification, Don't use !!! - * No leased lines, no X75, but many changes. - * - * Revision 1.2 1998/04/15 16:47:16 keil - * new interface - * - * Revision 1.1 1997/10/29 18:51:20 keil - * New files + * This file is (c) under GNU PUBLIC LICENSE * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/arcofi.h linux/drivers/isdn/hisax/arcofi.h --- v2.4.0-test5/linux/drivers/isdn/hisax/arcofi.h Wed Feb 16 17:03:52 2000 +++ linux/drivers/isdn/hisax/arcofi.h Sun Aug 6 12:43:41 2000 @@ -1,27 +1,10 @@ -/* $Id: arcofi.h,v 1.5 1999/12/23 15:09:32 keil Exp $ - +/* $Id: arcofi.h,v 1.6 2000/06/26 08:59:12 keil Exp $ + * * arcofi.h Ansteuerung ARCOFI 2165 * * Author Karsten Keil (keil@isdn4linux.de) * - * - * - * $Log: arcofi.h,v $ - * Revision 1.5 1999/12/23 15:09:32 keil - * change email - * - * Revision 1.4 1999/07/01 08:11:18 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 1.3 1998/05/25 12:57:39 keil - * HiSax golden code from certification, Don't use !!! - * No leased lines, no X75, but many changes. - * - * Revision 1.2 1998/04/15 16:47:17 keil - * new interface - * - * Revision 1.1 1997/10/29 18:51:20 keil - * New files + * This file is (c) under GNU PUBLIC LICENSE * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/asuscom.c linux/drivers/isdn/hisax/asuscom.c --- v2.4.0-test5/linux/drivers/isdn/hisax/asuscom.c Wed Feb 16 17:03:52 2000 +++ linux/drivers/isdn/hisax/asuscom.c Sun Aug 6 12:43:41 2000 @@ -1,39 +1,12 @@ -/* $Id: asuscom.c,v 1.9 1999/12/19 13:09:41 keil Exp $ - +/* $Id: asuscom.c,v 1.10 2000/06/26 08:59:12 keil Exp $ + * * asuscom.c low level stuff for ASUSCOM NETWORK INC. ISDNLink cards * * Author Karsten Keil (keil@isdn4linux.de) * * Thanks to ASUSCOM NETWORK INC. Taiwan and Dynalink NL for informations * - * - * $Log: asuscom.c,v $ - * Revision 1.9 1999/12/19 13:09:41 keil - * changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for - * signal proof delays - * - * Revision 1.8 1999/09/04 06:20:05 keil - * Changes from kernel set_current_state() - * - * Revision 1.7 1999/07/12 21:04:53 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 1.6 1999/07/01 08:11:18 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 1.5 1998/11/15 23:54:19 keil - * changes from 2.0 - * - * Revision 1.4 1998/06/18 23:18:20 keil - * Support for new IPAC card - * - * Revision 1.3 1998/04/15 16:46:53 keil - * new init code - * - * Revision 1.2 1998/02/02 13:27:06 keil - * New - * + * This file is (c) under GNU PUBLIC LICENSE * */ @@ -46,7 +19,7 @@ extern const char *CardType[]; -const char *Asuscom_revision = "$Revision: 1.9 $"; +const char *Asuscom_revision = "$Revision: 1.10 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/avm_a1.c linux/drivers/isdn/hisax/avm_a1.c --- v2.4.0-test5/linux/drivers/isdn/hisax/avm_a1.c Thu Nov 11 20:11:37 1999 +++ linux/drivers/isdn/hisax/avm_a1.c Sun Aug 6 12:43:41 2000 @@ -1,66 +1,10 @@ -/* $Id: avm_a1.c,v 2.11 1999/07/12 21:04:54 keil Exp $ - +/* $Id: avm_a1.c,v 2.12 2000/06/26 08:59:12 keil Exp $ + * * avm_a1.c low level stuff for AVM A1 (Fritz) isdn cards * * Author Karsten Keil (keil@isdn4linux.de) * - * - * $Log: avm_a1.c,v $ - * Revision 2.11 1999/07/12 21:04:54 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 2.10 1998/11/15 23:54:21 keil - * changes from 2.0 - * - * Revision 2.9 1998/08/13 23:36:12 keil - * HiSax 3.1 - don't work stable with current LinkLevel - * - * Revision 2.8 1998/04/15 16:44:27 keil - * new init code - * - * Revision 2.7 1998/02/02 13:29:37 keil - * fast io - * - * Revision 2.6 1998/01/13 23:09:46 keil - * really disable timer - * - * Revision 2.5 1998/01/02 06:50:29 calle - * Perodic timer of A1 now disabled, no need for linux driver. - * - * Revision 2.4 1997/11/08 21:35:42 keil - * new l1 init - * - * Revision 2.3 1997/11/06 17:13:32 keil - * New 2.1 init code - * - * Revision 2.2 1997/10/29 18:55:48 keil - * changes for 2.1.60 (irq2dev_map) - * - * Revision 2.1 1997/07/27 21:47:13 keil - * new interface structures - * - * Revision 2.0 1997/06/26 11:02:48 keil - * New Layer and card interface - * - * Revision 1.6 1997/04/13 19:54:07 keil - * Change in IRQ check delay for SMP - * - * Revision 1.5 1997/04/06 22:54:10 keil - * Using SKB's - * - * Revision 1.4 1997/01/27 15:50:21 keil - * SMP proof,cosmetics - * - * Revision 1.3 1997/01/21 22:14:20 keil - * cleanups - * - * Revision 1.2 1996/10/27 22:07:31 keil - * cosmetic changes - * - * Revision 1.1 1996/10/13 20:04:49 keil - * Initial revision - * + * This file is (c) under GNU PUBLIC LICENSE * */ #define __NO_VERSION__ @@ -70,7 +14,7 @@ #include "isdnl1.h" extern const char *CardType[]; -static const char *avm_revision = "$Revision: 2.11 $"; +static const char *avm_revision = "$Revision: 2.12 $"; #define AVM_A1_STAT_ISAC 0x01 #define AVM_A1_STAT_HSCX 0x02 diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/avm_a1p.c linux/drivers/isdn/hisax/avm_a1p.c --- v2.4.0-test5/linux/drivers/isdn/hisax/avm_a1p.c Thu Nov 11 20:11:37 1999 +++ linux/drivers/isdn/hisax/avm_a1p.c Sun Aug 6 12:43:41 2000 @@ -1,4 +1,4 @@ -/* $Id: avm_a1p.c,v 2.5 1999/09/01 08:26:34 calle Exp $ +/* $Id: avm_a1p.c,v 2.6 2000/06/26 08:59:12 keil Exp $ * * avm_a1p.c low level stuff for the following AVM cards: * A1 PCMCIA @@ -7,29 +7,7 @@ * * Author Carsten Paeth (calle@calle.in-berlin.de) * - * $Log: avm_a1p.c,v $ - * Revision 2.5 1999/09/01 08:26:34 calle - * Patch from Daniel Beichl to make A1 PCMCIA work again. - * - * Revision 2.4 1999/07/12 21:04:55 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 2.3 1998/11/15 23:54:22 keil - * changes from 2.0 - * - * Revision 2.2 1998/08/13 23:36:13 keil - * HiSax 3.1 - don't work stable with current LinkLevel - * - * Revision 2.1 1998/07/15 15:01:23 calle - * Support for AVM passive PCMCIA cards: - * A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0 - * - * Revision 1.1.2.1 1998/07/15 14:43:26 calle - * Support for AVM passive PCMCIA cards: - * A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0 - * - * + * This file is (c) under GNU PUBLIC LICENSE */ #define __NO_VERSION__ #include "hisax.h" @@ -74,7 +52,7 @@ #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) -static const char *avm_revision = "$Revision: 2.5 $"; +static const char *avm_revision = "$Revision: 2.6 $"; static inline u_char ReadISAC(struct IsdnCardState *cs, u_char offset) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/avm_pci.c linux/drivers/isdn/hisax/avm_pci.c --- v2.4.0-test5/linux/drivers/isdn/hisax/avm_pci.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/isdn/hisax/avm_pci.c Sun Aug 6 12:43:41 2000 @@ -1,60 +1,11 @@ -/* $Id: avm_pci.c,v 1.15 2000/02/26 00:35:12 keil Exp $ - +/* $Id: avm_pci.c,v 1.17 2000/06/26 08:59:12 keil Exp $ + * * avm_pci.c low level stuff for AVM Fritz!PCI and ISA PnP isdn cards * Thanks to AVM, Berlin for informations * * Author Karsten Keil (keil@isdn4linux.de) * - * - * $Log: avm_pci.c,v $ - * Revision 1.15 2000/02/26 00:35:12 keil - * Fix skb freeing in interrupt context - * - * Revision 1.14 1999/12/19 13:09:41 keil - * changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for - * signal proof delays - * - * Revision 1.13 1999/12/03 12:10:14 keil - * Bugfix: Wrong channel use on hangup of channel 2 - * - * Revision 1.12 1999/09/04 06:20:05 keil - * Changes from kernel set_current_state() - * - * Revision 1.11 1999/08/11 21:01:18 keil - * new PCI codefix - * - * Revision 1.10 1999/08/10 16:01:44 calle - * struct pci_dev changed in 2.3.13. Made the necessary changes. - * - * Revision 1.9 1999/07/12 21:04:57 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 1.8 1999/07/01 08:11:19 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 1.7 1999/02/22 18:26:30 keil - * Argh ! ISAC address was only set with PCI - * - * Revision 1.6 1998/11/27 19:59:28 keil - * set subtype for Fritz!PCI - * - * Revision 1.5 1998/11/27 12:56:45 keil - * forgot to update setup function name - * - * Revision 1.4 1998/11/15 23:53:19 keil - * Fritz!PnP; changes from 2.0 - * - * Revision 1.3 1998/09/27 23:53:39 keil - * Fix error handling - * - * Revision 1.2 1998/09/27 12:54:55 keil - * bcs assign was lost in setstack, very bad results - * - * Revision 1.1 1998/08/20 13:47:30 keil - * first version - * - * + * This file is (c) under GNU PUBLIC LICENSE * */ #define __NO_VERSION__ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/bkm_a4t.c linux/drivers/isdn/hisax/bkm_a4t.c --- v2.4.0-test5/linux/drivers/isdn/hisax/bkm_a4t.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/isdn/hisax/bkm_a4t.c Sun Aug 6 12:43:41 2000 @@ -1,4 +1,4 @@ -/* $Id: bkm_a4t.c,v 1.9 1999/12/19 13:09:41 keil Exp $ +/* $Id: bkm_a4t.c,v 1.11 2000/06/26 08:59:12 keil Exp $ * bkm_a4t.c low level stuff for T-Berkom A4T * derived from the original file sedlbauer.c * derived from the original file niccy.c @@ -6,36 +6,7 @@ * * Author Roland Klabunde (R.Klabunde@Berkom.de) * - * $Log: bkm_a4t.c,v $ - * Revision 1.9 1999/12/19 13:09:41 keil - * changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for - * signal proof delays - * - * Revision 1.8 1999/09/04 06:20:05 keil - * Changes from kernel set_current_state() - * - * Revision 1.7 1999/08/22 20:26:55 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.6 1999/08/11 21:01:22 keil - * new PCI codefix - * - * Revision 1.5 1999/08/10 16:01:46 calle - * struct pci_dev changed in 2.3.13. Made the necessary changes. - * - * Revision 1.4 1999/07/14 11:43:14 keil - * correct PCI_SUBSYSTEM_VENDOR_ID - * - * Revision 1.3 1999/07/12 21:04:58 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 1.2 1999/07/01 08:07:53 keil - * Initial version - * + * This file is (c) under GNU PUBLIC LICENSE * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/bkm_a8.c linux/drivers/isdn/hisax/bkm_a8.c --- v2.4.0-test5/linux/drivers/isdn/hisax/bkm_a8.c Wed Feb 16 17:03:52 2000 +++ linux/drivers/isdn/hisax/bkm_a8.c Sun Aug 6 12:43:41 2000 @@ -1,4 +1,4 @@ -/* $Id: bkm_a8.c,v 1.9 1999/12/19 13:09:41 keil Exp $ +/* $Id: bkm_a8.c,v 1.12 2000/06/26 08:59:12 keil Exp $ * bkm_a8.c low level stuff for Scitel Quadro (4*S0, passive) * derived from the original file sedlbauer.c * derived from the original file niccy.c @@ -6,36 +6,7 @@ * * Author Roland Klabunde (R.Klabunde@Berkom.de) * - * $Log: bkm_a8.c,v $ - * Revision 1.9 1999/12/19 13:09:41 keil - * changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for - * signal proof delays - * - * Revision 1.8 1999/09/04 06:20:05 keil - * Changes from kernel set_current_state() - * - * Revision 1.7 1999/08/22 20:26:58 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.6 1999/08/11 21:01:24 keil - * new PCI codefix - * - * Revision 1.5 1999/08/10 16:01:48 calle - * struct pci_dev changed in 2.3.13. Made the necessary changes. - * - * Revision 1.4 1999/07/14 11:43:15 keil - * correct PCI_SUBSYSTEM_VENDOR_ID - * - * Revision 1.3 1999/07/12 21:04:59 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 1.2 1999/07/01 08:07:54 keil - * Initial version - * + * This file is (c) under GNU PUBLIC LICENSE * */ #define __NO_VERSION__ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/bkm_ax.h linux/drivers/isdn/hisax/bkm_ax.h --- v2.4.0-test5/linux/drivers/isdn/hisax/bkm_ax.h Thu Aug 12 09:42:33 1999 +++ linux/drivers/isdn/hisax/bkm_ax.h Sun Aug 6 12:43:41 2000 @@ -1,13 +1,9 @@ -/* $Id: bkm_ax.h,v 1.2 1999/07/01 08:07:55 keil Exp $ +/* $Id: bkm_ax.h,v 1.4 2000/06/26 08:59:12 keil Exp $ * bkm_ax.h low level decls for T-Berkom cards A4T and Scitel Quadro (4*S0, passive) * * Author Roland Klabunde (R.Klabunde@Berkom.de) * - * $Log: bkm_ax.h,v $ - * Revision 1.2 1999/07/01 08:07:55 keil - * Initial version - * - * + * This file is (c) under GNU PUBLIC LICENSE * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/callc.c linux/drivers/isdn/hisax/callc.c --- v2.4.0-test5/linux/drivers/isdn/hisax/callc.c Mon Mar 27 08:08:25 2000 +++ linux/drivers/isdn/hisax/callc.c Tue Aug 8 09:31:00 2000 @@ -1,5 +1,5 @@ -/* $Id: callc.c,v 2.41 2000/03/17 07:07:42 kai Exp $ - +/* $Id: callc.c,v 2.47 2000/06/26 08:59:12 keil Exp $ + * * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden * @@ -10,156 +10,6 @@ * Thanks to Jan den Ouden * Fritz Elfert * - * $Log: callc.c,v $ - * Revision 2.41 2000/03/17 07:07:42 kai - * fixed oops when dialing out without l3 protocol selected - * - * Revision 2.40 1999/12/19 12:59:56 keil - * fix leased line handling - * and cosmetics - * - * Revision 2.39 1999/10/14 20:25:28 keil - * add a statistic for error monitoring - * - * Revision 2.38 1999/10/11 22:16:27 keil - * Suspend/Resume is possible without explicit ID too - * - * Revision 2.37 1999/09/20 19:49:47 keil - * Fix wrong init of PStack - * - * Revision 2.36 1999/09/20 12:13:13 keil - * Fix hang if no protocol was selected - * - * Revision 2.35 1999/09/04 06:20:05 keil - * Changes from kernel set_current_state() - * - * Revision 2.34 1999/08/25 20:02:34 werner - * Changed return values for stat_icall(w) from 3->4 and 4->5 because of conflicts - * with existing software definitions. (PtP incomplete called party number) - * - * Revision 2.33 1999/08/25 17:00:09 keil - * Make ISAR V32bis modem running - * Make LL->HL interface open for additional commands - * - * Revision 2.32 1999/08/22 20:27:01 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 2.31 1999/08/05 20:43:10 keil - * ISAR analog modem support - * - * Revision 2.30 1999/07/25 16:24:04 keil - * Fixed TEI now working again - * - * Revision 2.29 1999/07/13 21:05:41 werner - * Modified set_channel_limit to use new callback ISDN_STAT_DISCH. - * - * Revision 2.28 1999/07/09 08:30:02 keil - * cosmetics - * - * Revision 2.27 1999/07/05 23:51:38 werner - * Allow limiting of available HiSax B-chans per card. Controlled by hisaxctrl - * hisaxctrl id 10 - * - * Revision 2.26 1999/07/01 08:11:21 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 2.25 1999/01/02 11:17:20 keil - * Changes for 2.2 - * - * Revision 2.24 1998/11/15 23:54:24 keil - * changes from 2.0 - * - * Revision 2.23 1998/09/30 22:21:57 keil - * cosmetics - * - * Revision 2.22 1998/08/20 13:50:29 keil - * More support for hybrid modem (not working yet) - * - * Revision 2.21 1998/08/13 23:36:15 keil - * HiSax 3.1 - don't work stable with current LinkLevel - * - * Revision 2.20 1998/06/26 15:13:05 fritz - * Added handling of STAT_ICALL with incomplete CPN. - * Added AT&L for ttyI emulator. - * Added more locking stuff in tty_write. - * - * Revision 2.19 1998/05/25 14:08:06 keil - * HiSax 3.0 - * fixed X.75 and leased line to work again - * Point2Point and fixed TEI are runtime options now: - * hisaxctrl 7 1 set PTP - * hisaxctrl 8 - * set fixed TEI to TEIVALUE (0-63) - * - * Revision 2.18 1998/05/25 12:57:40 keil - * HiSax golden code from certification, Don't use !!! - * No leased lines, no X75, but many changes. - * - * Revision 2.17 1998/04/15 16:46:06 keil - * RESUME support - * - * Revision 2.16 1998/04/10 10:35:17 paul - * fixed (silly?) warnings from egcs on Alpha. - * - * Revision 2.15 1998/03/19 13:18:37 keil - * Start of a CAPI like interface for supplementary Service - * first service: SUSPEND - * - * Revision 2.14 1998/03/07 22:56:54 tsbogend - * made HiSax working on Linux/Alpha - * - * Revision 2.13 1998/02/12 23:07:16 keil - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 2.12 1998/02/09 10:55:54 keil - * New leased line mode - * - * Revision 2.11 1998/02/02 13:35:19 keil - * config B-channel delay - * - * Revision 2.10 1997/11/06 17:09:15 keil - * New 2.1 init code - * - * Revision 2.9 1997/10/29 19:01:58 keil - * new LL interface - * - * Revision 2.8 1997/10/10 20:56:44 fritz - * New HL interface. - * - * Revision 2.7 1997/10/01 09:21:28 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 2.6 1997/09/11 17:26:58 keil - * Open B-channel if here are incomming packets - * - * Revision 2.5 1997/08/07 17:46:05 keil - * Fix Incomming Call without broadcast - * - * Revision 2.4 1997/08/03 14:37:58 keil - * Activate Layer2 in PtP mode - * - * Revision 2.3 1997/07/31 19:23:40 keil - * LAYER2_WATCHING for PtP - * - * Revision 2.2 1997/07/31 11:48:18 keil - * experimental REJECT after ALERTING - * - * Revision 2.1 1997/07/30 17:12:59 keil - * more changes for 'One TEI per card' - * - * Revision 2.0 1997/07/27 21:12:21 keil - * CRef based L3; new channel handling; many other stuff - * - * Revision 1.31 1997/06/26 11:09:23 keil - * New managment and minor changes - * - * old logs removed /KKe - * */ #define __NO_VERSION__ @@ -170,7 +20,7 @@ #define MOD_USE_COUNT ( GET_USE_COUNT (&__this_module)) #endif /* MODULE */ -const char *lli_revision = "$Revision: 2.41 $"; +const char *lli_revision = "$Revision: 2.47 $"; extern struct IsdnCard cards[]; extern int nrcards; @@ -516,7 +366,7 @@ * No need to return "unknown" for calls without OAD, * cause that's handled in linklevel now (replaced by '0') */ - ic.parm.setup = chanp->proc->para.setup; + memcpy (&ic.parm.setup, &chanp->proc->para.setup, sizeof(ic.parm.setup)); ret = chanp->cs->iif.statcallb(&ic); if (chanp->debug & 1) link_debug(chanp, 1, "statcallb ret=%d", ret); @@ -533,7 +383,7 @@ FsmChangeState(fi, ST_IN_PROCEED_SEND); chanp->d_st->lli.l4l3(chanp->d_st, CC_PROCEED_SEND | REQUEST, chanp->proc); if (ret == 5) { - chanp->setup = ic.parm.setup; + memcpy (&chanp->setup, &ic.parm.setup, sizeof(chanp->setup)); chanp->d_st->lli.l4l3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc); } break; @@ -1656,7 +1506,7 @@ link_debug(chanp, 1, "DIAL %s -> %s (%d,%d)", ic->parm.setup.eazmsn, ic->parm.setup.phone, ic->parm.setup.si1, ic->parm.setup.si2); - chanp->setup = ic->parm.setup; + memcpy (&chanp->setup, &ic->parm.setup, sizeof (chanp->setup)); if (!strcmp(chanp->setup.eazmsn, "0")) chanp->setup.eazmsn[0] = '\0'; /* this solution is dirty and may be change, if @@ -1872,7 +1722,7 @@ chanp = csta->channel + ic->arg; if (chanp->debug & 1) link_debug(chanp, 1, "REDIR"); - chanp->setup = ic->parm.setup; + memcpy (&chanp->setup, &ic->parm.setup, sizeof(chanp->setup)); FsmEvent(&chanp->fi, EV_REDIR, NULL); break; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/cert.c linux/drivers/isdn/hisax/cert.c --- v2.4.0-test5/linux/drivers/isdn/hisax/cert.c Thu Aug 12 09:42:33 1999 +++ linux/drivers/isdn/hisax/cert.c Sun Aug 6 12:43:41 2000 @@ -1,21 +1,10 @@ -/* $Id: cert.c,v 2.2 1999/08/07 17:35:05 keil Exp $ - +/* $Id: cert.c,v 2.3 2000/06/26 08:59:12 keil Exp $ + * * Author Karsten Keil (keil@isdn4linux.de) * * This file is (c) under GNU PUBLIC LICENSE * For changes and modifications please read * ../../../Documentation/isdn/HiSax.cert - * - * $Log: cert.c,v $ - * Revision 2.2 1999/08/07 17:35:05 keil - * approval for Eicon Technology Diva 2.01 PCI - * - * Revision 2.1 1998/11/15 23:51:15 keil - * certification stuff - * - * Revision 1.2.2.1 1998/11/03 21:46:37 keil - * first version - * * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/config.c linux/drivers/isdn/hisax/config.c --- v2.4.0-test5/linux/drivers/isdn/hisax/config.c Sat Feb 26 22:31:45 2000 +++ linux/drivers/isdn/hisax/config.c Sun Aug 6 12:43:41 2000 @@ -1,161 +1,9 @@ -/* $Id: config.c,v 2.44 2000/02/26 00:35:12 keil Exp $ - +/* $Id: config.c,v 2.50 2000/07/04 10:24:32 keil Exp $ + * * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden * - * - * $Log: config.c,v $ - * Revision 2.44 2000/02/26 00:35:12 keil - * Fix skb freeing in interrupt context - * - * Revision 2.43 2000/01/20 19:49:36 keil - * Support teles 13.3c vendor version 2.1 - * - * Revision 2.42 1999/12/19 13:09:41 keil - * changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for - * signal proof delays - * - * Revision 2.41 1999/11/18 00:00:43 werner - * - * Added support for HFC-S+ and HFC-SP cards - * - * Revision 2.40 1999/10/30 13:09:45 keil - * Version 3.3c - * - * Revision 2.39 1999/10/16 14:44:45 keil - * Fix module parm if only NICCY was selected - * - * Revision 2.38 1999/10/14 20:25:28 keil - * add a statistic for error monitoring - * - * Revision 2.37 1999/09/20 12:11:08 keil - * Fix hang if no protocol was selected - * - * Revision 2.36 1999/09/07 05:43:58 werner - * - * Added io as parameter 0 for HFC-PCI cards, if manual selection needed. - * - * Revision 2.35 1999/09/04 06:35:09 keil - * Winbond W6692 support - * - * Revision 2.34 1999/09/04 06:20:06 keil - * Changes from kernel set_current_state() - * - * Revision 2.33 1999/08/30 11:57:52 keil - * Fix broken avm pcmcia - * - * Revision 2.32 1999/08/28 22:11:10 keil - * __setup function should be static - * - * Revision 2.31 1999/08/25 16:47:43 keil - * Support new __setup; allow to add FEATURES after register_isdn - * - * Revision 2.30 1999/08/05 20:43:14 keil - * ISAR analog modem support - * - * Revision 2.29 1999/07/21 14:46:00 keil - * changes from EICON certification - * - * Revision 2.28 1999/07/14 12:38:36 werner - * Added changes for echo channel handling - * - * Revision 2.27 1999/07/12 21:05:00 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 2.26 1999/07/08 21:27:17 keil - * version 3.2 - * - * Revision 2.25 1999/07/05 23:51:44 werner - * Allow limiting of available HiSax B-chans per card. Controlled by hisaxctrl - * hisaxctrl id 10 - * - * Revision 2.24 1999/07/01 08:11:26 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 2.23 1999/02/17 10:53:02 cpetig - * Added Hisax_closecard to exported symbols. - * As indicated by Oliver Schoett . - * - * If anyone is annoyed by exporting symbols deep inside the code, please - * contact me. - * - * Revision 2.22 1999/02/04 21:41:53 keil - * Fix printk msg - * - * Revision 2.21 1999/02/04 10:48:52 keil - * Fix readstat bug - * - * Revision 2.20 1998/11/15 23:54:28 keil - * changes from 2.0 - * - * Revision 2.19 1998/08/13 23:36:18 keil - * HiSax 3.1 - don't work stable with current LinkLevel - * - * Revision 2.18 1998/07/30 21:01:37 niemann - * Fixed Sedlbauer Speed Fax PCMCIA missing isdnl3new - * - * Revision 2.17 1998/07/15 15:01:26 calle - * Support for AVM passive PCMCIA cards: - * A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0 - * - * Revision 2.16 1998/05/25 14:10:03 keil - * HiSax 3.0 - * X.75 and leased are working again. - * - * Revision 2.15 1998/05/25 12:57:43 keil - * HiSax golden code from certification, Don't use !!! - * No leased lines, no X75, but many changes. - * - * Revision 2.14 1998/04/15 16:38:25 keil - * Add S0Box and Teles PCI support - * - * Revision 2.13 1998/03/09 23:19:23 keil - * Changes for PCMCIA - * - * Revision 2.12 1998/02/11 17:28:02 keil - * Niccy PnP/PCI support - * - * Revision 2.11 1998/02/09 21:26:13 keil - * fix export module for 2.1 - * - * Revision 2.10 1998/02/09 18:46:05 keil - * Support for Sedlbauer PCMCIA (Marcus Niemann) - * - * Revision 2.9 1998/02/03 23:31:28 keil - * add AMD7930 support - * - * Revision 2.8 1998/02/02 13:32:59 keil - * New card support - * - * Revision 2.7 1998/01/31 21:41:44 keil - * changes for newer 2.1 kernels - * - * Revision 2.6 1997/11/08 21:35:43 keil - * new l1 init - * - * Revision 2.5 1997/11/06 17:15:08 keil - * New 2.1 init; PCMCIA wrapper changes - * - * Revision 2.4 1997/10/29 19:07:52 keil - * changes for 2.1 - * - * Revision 2.3 1997/10/01 09:21:33 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 2.2 1997/09/11 17:24:46 keil - * Add new cards - * - * Revision 2.1 1997/07/27 21:41:35 keil - * version change - * - * Revision 2.0 1997/06/26 11:06:28 keil - * New card and L1 interface. - * Eicon.Diehl Diva and Dynalink IS64PH support - * - * old changes removed /KKe + * This file is (c) under GNU PUBLIC LICENSE * */ #include diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/diva.c linux/drivers/isdn/hisax/diva.c --- v2.4.0-test5/linux/drivers/isdn/hisax/diva.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/isdn/hisax/diva.c Sun Aug 6 12:43:41 2000 @@ -1,5 +1,5 @@ -/* $Id: diva.c,v 1.19 2000/02/26 00:35:12 keil Exp $ - +/* $Id: diva.c,v 1.21 2000/06/26 08:59:12 keil Exp $ + * * diva.c low level stuff for Eicon.Diehl Diva Family ISDN cards * * Author Karsten Keil (keil@isdn4linux.de) @@ -10,70 +10,6 @@ * * Thanks to Eicon Technology for documents and informations * - * - * $Log: diva.c,v $ - * Revision 1.19 2000/02/26 00:35:12 keil - * Fix skb freeing in interrupt context - * - * Revision 1.18 1999/12/19 13:09:41 keil - * changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for - * signal proof delays - * - * Revision 1.17 1999/09/04 06:20:06 keil - * Changes from kernel set_current_state() - * - * Revision 1.16 1999/08/11 21:01:25 keil - * new PCI codefix - * - * Revision 1.15 1999/08/10 16:01:49 calle - * struct pci_dev changed in 2.3.13. Made the necessary changes. - * - * Revision 1.14 1999/08/07 17:35:08 keil - * approval for Eicon Technology Diva 2.01 PCI - * - * Revision 1.13 1999/07/21 14:46:07 keil - * changes from EICON certification - * - * Revision 1.12 1999/07/12 21:05:04 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 1.11 1999/07/01 08:11:29 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 1.10 1998/11/15 23:54:31 keil - * changes from 2.0 - * - * Revision 1.9 1998/06/27 22:52:03 keil - * support for Diva 2.01 - * - * Revision 1.8 1998/05/25 12:57:46 keil - * HiSax golden code from certification, Don't use !!! - * No leased lines, no X75, but many changes. - * - * Revision 1.7 1998/04/15 16:42:36 keil - * new init code - * new PCI init (2.1.94) - * - * Revision 1.6 1998/03/07 22:56:57 tsbogend - * made HiSax working on Linux/Alpha - * - * Revision 1.5 1998/02/02 13:29:38 keil - * fast io - * - * Revision 1.4 1997/11/08 21:35:44 keil - * new l1 init - * - * Revision 1.3 1997/11/06 17:13:33 keil - * New 2.1 init code - * - * Revision 1.2 1997/10/29 18:55:55 keil - * changes for 2.1.60 (irq2dev_map) - * - * Revision 1.1 1997/09/18 17:11:20 keil - * first version - * - * */ #define __NO_VERSION__ @@ -87,7 +23,7 @@ extern const char *CardType[]; -const char *Diva_revision = "$Revision: 1.19 $"; +const char *Diva_revision = "$Revision: 1.21 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/elsa.c linux/drivers/isdn/hisax/elsa.c --- v2.4.0-test5/linux/drivers/isdn/hisax/elsa.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/isdn/hisax/elsa.c Sun Aug 6 12:43:41 2000 @@ -1,5 +1,5 @@ -/* $Id: elsa.c,v 2.20 1999/12/19 13:09:42 keil Exp $ - +/* $Id: elsa.c,v 2.23 2000/06/26 08:59:12 keil Exp $ + * * elsa.c low level stuff for Elsa isdn cards * * Author Karsten Keil (keil@isdn4linux.de) @@ -12,80 +12,6 @@ * * Klaus Lichtenwalder (Klaus.Lichtenwalder@WebForum.DE) * for ELSA PCMCIA support - * - * $Log: elsa.c,v $ - * Revision 2.20 1999/12/19 13:09:42 keil - * changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for - * signal proof delays - * - * Revision 2.19 1999/09/04 06:20:06 keil - * Changes from kernel set_current_state() - * - * Revision 2.18 1999/08/25 16:50:54 keil - * Fix bugs which cause 2.3.14 hangs (waitqueue init) - * - * Revision 2.17 1999/08/11 20:57:40 keil - * bugfix IPAC version 1.1 - * new PCI codefix - * - * Revision 2.16 1999/08/10 16:01:51 calle - * struct pci_dev changed in 2.3.13. Made the necessary changes. - * - * Revision 2.15 1999/08/09 19:25:21 keil - * Support (alpha version) for the '98 model of ELSA Microlink ISDN/MC - * by Christer Weinigel, Cendio Systems AB - * Add support for IPAC 1.2 - * - * Revision 2.14 1999/07/12 21:05:07 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 2.13 1999/07/01 08:11:31 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 2.12 1998/11/15 23:54:35 keil - * changes from 2.0 - * - * Revision 2.11 1998/08/20 13:50:34 keil - * More support for hybrid modem (not working yet) - * - * Revision 2.10 1998/08/13 23:36:22 keil - * HiSax 3.1 - don't work stable with current LinkLevel - * - * Revision 2.9 1998/05/25 12:57:48 keil - * HiSax golden code from certification, Don't use !!! - * No leased lines, no X75, but many changes. - * - * Revision 2.8 1998/04/15 16:41:42 keil - * QS3000 PCI support - * new init code - * new PCI init (2.1.94) - * - * Revision 2.7 1998/03/07 22:56:58 tsbogend - * made HiSax working on Linux/Alpha - * - * Revision 2.6 1998/02/02 13:29:40 keil - * fast io - * - * Revision 2.5 1998/01/31 21:41:45 keil - * changes for newer 2.1 kernels - * - * Revision 2.4 1997/11/08 21:35:46 keil - * new l1 init - * - * Revision 2.3 1997/11/06 17:15:09 keil - * New 2.1 init; PCMCIA wrapper changes - * - * Revision 2.2 1997/10/29 18:57:09 keil - * changes for 2.1.60, arcofi support - * - * Revision 2.1 1997/07/27 21:47:08 keil - * new interface structures - * - * Revision 2.0 1997/06/26 11:02:40 keil - * New Layer and card interface - * - * old changes removed KKe * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/elsa_ser.c linux/drivers/isdn/hisax/elsa_ser.c --- v2.4.0-test5/linux/drivers/isdn/hisax/elsa_ser.c Sat Feb 26 22:31:45 2000 +++ linux/drivers/isdn/hisax/elsa_ser.c Sun Aug 6 12:43:41 2000 @@ -1,3 +1,10 @@ +/* $Id: elsa_ser.c,v 2.9 2000/06/26 08:59:12 keil Exp $ + * + * stuff for the serial modem on ELSA cards + * + * This file is (c) under GNU PUBLIC LICENSE + * + */ #include #include #include diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/fsm.c linux/drivers/isdn/hisax/fsm.c --- v2.4.0-test5/linux/drivers/isdn/hisax/fsm.c Thu May 11 15:30:07 2000 +++ linux/drivers/isdn/hisax/fsm.c Sun Aug 6 12:43:41 2000 @@ -1,48 +1,12 @@ -/* $Id: fsm.c,v 1.11 1999/12/23 15:09:32 keil Exp $ - +/* $Id: fsm.c,v 1.13 2000/06/26 08:59:12 keil Exp $ + * * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden * * Thanks to Jan den Ouden * Fritz Elfert * - * $Log: fsm.c,v $ - * Revision 1.11 1999/12/23 15:09:32 keil - * change email - * - * Revision 1.10 1998/11/15 23:54:39 keil - * changes from 2.0 - * - * Revision 1.9 1998/03/26 07:10:02 paul - * The jumpmatrix table in struct Fsm was an array of "int". This is not - * large enough for pointers to functions on Linux/Alpha (instant crash - * on "insmod hisax). Now there is a typedef for the pointer to function. - * This also prevents warnings about "incompatible pointer types". - * - * Revision 1.8 1998/03/07 22:56:59 tsbogend - * made HiSax working on Linux/Alpha - * - * Revision 1.7 1997/11/06 17:09:13 keil - * New 2.1 init code - * - * Revision 1.6 1997/07/27 21:42:25 keil - * proof Fsm routines - * - * Revision 1.5 1997/06/26 11:10:05 keil - * Restart timer function added - * - * Revision 1.4 1997/04/06 22:56:42 keil - * Some cosmetic changes - * - * Revision 1.3 1997/02/16 01:04:08 fritz - * Bugfix: Changed timer handling caused hang with 2.1.X - * - * Revision 1.2 1997/01/09 20:57:27 keil - * cleanup & FSM_TIMER_DEBUG - * - * Revision 1.1 1996/10/13 20:04:52 keil - * Initial revision - * + * This file is (c) under GNU PUBLIC LICENSE * */ #define __NO_VERSION__ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/gazel.c linux/drivers/isdn/hisax/gazel.c --- v2.4.0-test5/linux/drivers/isdn/hisax/gazel.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/isdn/hisax/gazel.c Sun Aug 6 12:43:41 2000 @@ -1,32 +1,11 @@ -/* $Id: gazel.c,v 2.6 1999/08/22 20:27:03 calle Exp $ - +/* $Id: gazel.c,v 2.8 2000/06/26 08:59:12 keil Exp $ + * * gazel.c low level stuff for Gazel isdn cards * * Author BeWan Systems * based on source code from Karsten Keil * - * $Log: gazel.c,v $ - * Revision 2.6 1999/08/22 20:27:03 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 2.5 1999/08/11 21:01:26 keil - * new PCI codefix - * - * Revision 2.4 1999/08/10 16:01:54 calle - * struct pci_dev changed in 2.3.13. Made the necessary changes. - * - * Revision 2.3 1999/07/12 21:05:09 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 2.1 1999/07/08 21:26:17 keil - * new card - * - * Revision 1.0 1999/28/06 - * Initial revision + * This file is (c) under GNU PUBLIC LICENSE * */ #include @@ -39,7 +18,7 @@ #include extern const char *CardType[]; -const char *gazel_revision = "$Revision: 2.6 $"; +const char *gazel_revision = "$Revision: 2.8 $"; #define R647 1 #define R685 2 diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/hfc_2bds0.c linux/drivers/isdn/hisax/hfc_2bds0.c --- v2.4.0-test5/linux/drivers/isdn/hisax/hfc_2bds0.c Sat Feb 26 22:31:45 2000 +++ linux/drivers/isdn/hisax/hfc_2bds0.c Sun Aug 6 12:43:41 2000 @@ -1,46 +1,10 @@ -/* $Id: hfc_2bds0.c,v 1.12 2000/02/26 00:35:12 keil Exp $ +/* $Id: hfc_2bds0.c,v 1.13 2000/06/26 08:59:12 keil Exp $ * * specific routines for CCD's HFC 2BDS0 * * Author Karsten Keil (keil@isdn4linux.de) * - * - * $Log: hfc_2bds0.c,v $ - * Revision 1.12 2000/02/26 00:35:12 keil - * Fix skb freeing in interrupt context - * - * Revision 1.11 1999/12/23 15:09:32 keil - * change email - * - * Revision 1.10 1999/10/14 20:25:28 keil - * add a statistic for error monitoring - * - * Revision 1.9 1999/07/01 08:11:35 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 1.8 1998/11/15 23:54:40 keil - * changes from 2.0 - * - * Revision 1.7 1998/09/30 22:24:45 keil - * Fix missing line in setstack* - * - * Revision 1.6 1998/08/13 23:36:26 keil - * HiSax 3.1 - don't work stable with current LinkLevel - * - * Revision 1.5 1998/06/27 22:52:58 keil - * make 16.3c working with 3.0 - * - * Revision 1.4 1998/05/25 12:57:52 keil - * HiSax golden code from certification, Don't use !!! - * No leased lines, no X75, but many changes. - * - * Revision 1.3 1998/02/12 23:07:22 keil - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 1.2 1998/02/02 13:26:13 keil - * New - * - * + * This file is (c) under GNU PUBLIC LICENSE * */ #define __NO_VERSION__ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/hfc_2bds0.h linux/drivers/isdn/hisax/hfc_2bds0.h --- v2.4.0-test5/linux/drivers/isdn/hisax/hfc_2bds0.h Wed Feb 16 17:03:52 2000 +++ linux/drivers/isdn/hisax/hfc_2bds0.h Sun Aug 6 12:43:41 2000 @@ -1,18 +1,10 @@ -/* $Id: hfc_2bds0.h,v 1.3 1999/12/23 15:09:32 keil Exp $ - +/* $Id: hfc_2bds0.h,v 1.4 2000/06/26 08:59:12 keil Exp $ + * * specific defines for CCD's HFC 2BDS0 * * Author Karsten Keil (keil@isdn4linux.de) * - * - * $Log: hfc_2bds0.h,v $ - * Revision 1.3 1999/12/23 15:09:32 keil - * change email - * - * Revision 1.2 1998/02/02 13:26:15 keil - * New - * - * + * This file is (c) under GNU PUBLIC LICENSE * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/hfc_2bs0.c linux/drivers/isdn/hisax/hfc_2bs0.c --- v2.4.0-test5/linux/drivers/isdn/hisax/hfc_2bs0.c Sat Feb 26 22:31:45 2000 +++ linux/drivers/isdn/hisax/hfc_2bs0.c Sun Aug 6 12:43:41 2000 @@ -1,52 +1,10 @@ -/* $Id: hfc_2bs0.c,v 1.13 2000/02/26 00:35:12 keil Exp $ - +/* $Id: hfc_2bs0.c,v 1.14 2000/06/26 08:59:13 keil Exp $ + * * specific routines for CCD's HFC 2BS0 * * Author Karsten Keil (keil@isdn4linux.de) * - * - * $Log: hfc_2bs0.c,v $ - * Revision 1.13 2000/02/26 00:35:12 keil - * Fix skb freeing in interrupt context - * - * Revision 1.12 1999/12/19 14:17:12 keil - * fix compiler warning - * - * Revision 1.11 1999/11/21 12:41:18 werner - * - * Implemented full audio support - * - * Revision 1.10 1999/10/14 20:25:28 keil - * add a statistic for error monitoring - * - * Revision 1.9 1999/07/01 08:11:36 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 1.8 1998/11/15 23:54:43 keil - * changes from 2.0 - * - * Revision 1.7 1998/09/30 22:24:46 keil - * Fix missing line in setstack* - * - * Revision 1.6 1998/08/13 23:36:28 keil - * HiSax 3.1 - don't work stable with current LinkLevel - * - * Revision 1.5 1998/05/25 12:57:54 keil - * HiSax golden code from certification, Don't use !!! - * No leased lines, no X75, but many changes. - * - * Revision 1.4 1998/02/12 23:07:29 keil - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 1.3 1997/11/06 17:13:35 keil - * New 2.1 init code - * - * Revision 1.2 1997/10/29 19:04:47 keil - * changes for 2.1 - * - * Revision 1.1 1997/09/11 17:31:33 keil - * Common part for HFC 2BS0 based cards - * + * This file is (c) under GNU PUBLIC LICENSE * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/hfc_2bs0.h linux/drivers/isdn/hisax/hfc_2bs0.h --- v2.4.0-test5/linux/drivers/isdn/hisax/hfc_2bs0.h Wed Feb 16 17:03:52 2000 +++ linux/drivers/isdn/hisax/hfc_2bs0.h Sun Aug 6 12:43:41 2000 @@ -1,17 +1,10 @@ -/* $Id: hfc_2bs0.h,v 1.2 1999/12/23 15:09:32 keil Exp $ - +/* $Id: hfc_2bs0.h,v 1.3 2000/06/26 08:59:13 keil Exp $ + * * specific defines for CCD's HFC 2BS0 * * Author Karsten Keil (keil@isdn4linux.de) * - * - * $Log: hfc_2bs0.h,v $ - * Revision 1.2 1999/12/23 15:09:32 keil - * change email - * - * Revision 1.1 1997/09/11 17:31:34 keil - * Common part for HFC 2BS0 based cards - * + * This file is (c) under GNU PUBLIC LICENSE * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/hfc_pci.c linux/drivers/isdn/hisax/hfc_pci.c --- v2.4.0-test5/linux/drivers/isdn/hisax/hfc_pci.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/isdn/hisax/hfc_pci.c Sun Aug 6 12:43:41 2000 @@ -1,4 +1,4 @@ -/* $Id: hfc_pci.c,v 1.27 2000/02/26 00:35:12 keil Exp $ +/* $Id: hfc_pci.c,v 1.30 2000/06/26 08:59:13 keil Exp $ * hfc_pci.c low level driver for CCD´s hfc-pci based cards * @@ -22,101 +22,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Log: hfc_pci.c,v $ - * Revision 1.27 2000/02/26 00:35:12 keil - * Fix skb freeing in interrupt context - * - * Revision 1.26 2000/02/09 20:22:55 werner - * - * Updated PCI-ID table - * - * Revision 1.25 1999/12/19 13:09:42 keil - * changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for - * signal proof delays - * - * Revision 1.24 1999/11/17 23:59:55 werner - * - * removed unneeded data - * - * Revision 1.23 1999/11/07 17:01:55 keil - * fix for 2.3 pci structs - * - * Revision 1.22 1999/10/10 20:14:27 werner - * - * Correct B2-chan usage in conjuntion with echo mode. First implementation of NT-leased line mode. - * - * Revision 1.21 1999/10/02 17:47:49 werner - * - * Changed init order, added correction for page alignment with shared mem - * - * Revision 1.20 1999/09/07 06:18:55 werner - * - * Added io parameter for HFC-PCI based cards. Needed only with multiple cards - * when initialisation/selection order needs to be set. - * - * Revision 1.19 1999/09/04 06:20:06 keil - * Changes from kernel set_current_state() - * - * Revision 1.18 1999/08/29 17:05:44 werner - * corrected tx_lo line setup. Datasheet is not correct. - * - * Revision 1.17 1999/08/28 21:04:27 werner - * Implemented full audio support (transparent mode) - * - * Revision 1.16 1999/08/25 17:01:27 keil - * Use new LL->HL auxcmd call - * - * Revision 1.15 1999/08/22 20:27:05 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.14 1999/08/12 18:59:45 werner - * Added further manufacturer and device ids to PCI list - * - * Revision 1.13 1999/08/11 21:01:28 keil - * new PCI codefix - * - * Revision 1.12 1999/08/10 16:01:58 calle - * struct pci_dev changed in 2.3.13. Made the necessary changes. - * - * Revision 1.11 1999/08/09 19:13:32 werner - * moved constant pci ids to pci id table - * - * Revision 1.10 1999/08/08 10:17:34 werner - * added new PCI vendor and card ids for Manufacturer 0x1043 - * - * Revision 1.9 1999/08/07 21:09:10 werner - * Fixed another memcpy problem in fifo handling. - * Thanks for debugging aid by Olaf Kordwittenborg. - * - * Revision 1.8 1999/07/23 14:25:15 werner - * Some smaller bug fixes and prepared support for GCI/IOM bus - * - * Revision 1.7 1999/07/14 21:24:20 werner - * fixed memcpy problem when using E-channel feature - * - * Revision 1.6 1999/07/13 21:08:08 werner - * added echo channel logging feature. - * - * Revision 1.5 1999/07/12 21:05:10 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 1.4 1999/07/04 21:51:39 werner - * Changes to solve problems with irq sharing and smp machines - * Thanks to Karsten Keil and Alex Holden for giving aid with - * testing and debugging - * - * Revision 1.3 1999/07/01 09:43:19 keil - * removed additional schedules in timeouts - * - * Revision 1.2 1999/07/01 08:07:51 keil - * Initial version - * - * - * */ #include @@ -129,7 +34,7 @@ extern const char *CardType[]; -static const char *hfcpci_revision = "$Revision: 1.27 $"; +static const char *hfcpci_revision = "$Revision: 1.30 $"; /* table entry in the PCI devices list */ typedef struct { diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/hfc_pci.h linux/drivers/isdn/hisax/hfc_pci.h --- v2.4.0-test5/linux/drivers/isdn/hisax/hfc_pci.h Thu Nov 11 20:11:37 1999 +++ linux/drivers/isdn/hisax/hfc_pci.h Sun Aug 6 12:43:41 2000 @@ -1,5 +1,5 @@ -/* $Id: hfc_pci.h,v 1.7 1999/10/10 20:13:06 werner Exp $ - +/* $Id: hfc_pci.h,v 1.8 2000/06/26 08:59:13 keil Exp $ + * * specific defines for CCD's HFC 2BDS0 PCI chips * * Author Werner Cornelius (werner@isdn4linux.de) @@ -19,28 +19,6 @@ * 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. - * - * $Log: hfc_pci.h,v $ - * Revision 1.7 1999/10/10 20:13:06 werner - * - * Corrected timer constant - * - * Revision 1.6 1999/08/28 21:04:29 werner - * Implemented full audio support (transparent mode) - * - * Revision 1.5 1999/08/09 19:13:34 werner - * moved constant pci ids to pci id table - * - * Revision 1.4 1999/08/08 10:17:33 werner - * added new PCI vendor and card ids for Manufacturer 0x1043 - * - * Revision 1.3 1999/07/14 12:39:34 werner - * Added changes for echo handling. - * - * Revision 1.2 1999/07/01 08:07:52 keil - * Initial version - * - * * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/hfc_sx.c linux/drivers/isdn/hisax/hfc_sx.c --- v2.4.0-test5/linux/drivers/isdn/hisax/hfc_sx.c Thu Mar 2 14:36:22 2000 +++ linux/drivers/isdn/hisax/hfc_sx.c Sun Aug 6 12:43:41 2000 @@ -1,4 +1,4 @@ -/* $Id: hfc_sx.c,v 1.4 2000/02/26 00:35:12 keil Exp $ +/* $Id: hfc_sx.c,v 1.6 2000/06/26 08:59:13 keil Exp $ * hfc_sx.c low level driver for CCD´s hfc-s+/sp based cards * @@ -21,24 +21,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Log: hfc_sx.c,v $ - * Revision 1.4 2000/02/26 00:35:12 keil - * Fix skb freeing in interrupt context - * - * Revision 1.3 2000/01/20 19:49:36 keil - * Support teles 13.3c vendor version 2.1 - * - * Revision 1.2 1999/12/19 13:09:42 keil - * changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for - * signal proof delays - * - * Revision 1.1 1999/11/18 00:09:18 werner - * - * Initial release of files for HFC-S+ and HFC-SP cards with 32K-RAM. - * Audio and Echo are supported. - * - * - * */ #define __NO_VERSION__ @@ -49,7 +31,7 @@ extern const char *CardType[]; -static const char *hfcsx_revision = "$Revision: 1.4 $"; +static const char *hfcsx_revision = "$Revision: 1.6 $"; /***************************************/ /* IRQ-table for CCDs demo board */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/hfc_sx.h linux/drivers/isdn/hisax/hfc_sx.h --- v2.4.0-test5/linux/drivers/isdn/hisax/hfc_sx.h Wed Feb 16 17:03:52 2000 +++ linux/drivers/isdn/hisax/hfc_sx.h Sun Aug 6 12:43:41 2000 @@ -1,5 +1,5 @@ -/* $Id: hfc_sx.h,v 1.1 1999/11/18 00:09:18 werner Exp $ - +/* $Id: hfc_sx.h,v 1.2 2000/06/26 08:59:13 keil Exp $ + * * specific defines for CCD's HFC 2BDS0 S+,SP chips * * Author Werner Cornelius (werner@isdn4linux.de) @@ -19,14 +19,6 @@ * 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. - * - * $Log: hfc_sx.h,v $ - * Revision 1.1 1999/11/18 00:09:18 werner - * - * Initial release of files for HFC-S+ and HFC-SP cards with 32K-RAM. - * Audio and Echo are supported. - * - * * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/hfcscard.c linux/drivers/isdn/hisax/hfcscard.c --- v2.4.0-test5/linux/drivers/isdn/hisax/hfcscard.c Wed Feb 16 17:03:52 2000 +++ linux/drivers/isdn/hisax/hfcscard.c Sun Aug 6 12:43:41 2000 @@ -1,29 +1,10 @@ -/* $Id: hfcscard.c,v 1.6 1999/12/19 13:09:42 keil Exp $ - +/* $Id: hfcscard.c,v 1.7 2000/06/26 08:59:13 keil Exp $ + * * hfcscard.c low level stuff for hfcs based cards (Teles3c, ACER P10) * * Author Karsten Keil (keil@isdn4linux.de) * - * - * $Log: hfcscard.c,v $ - * Revision 1.6 1999/12/19 13:09:42 keil - * changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for - * signal proof delays - * - * Revision 1.5 1999/09/04 06:20:06 keil - * Changes from kernel set_current_state() - * - * Revision 1.4 1999/08/09 18:59:59 keil - * Fix S0 init - Thanks to Stefan Gybas - * - * Revision 1.3 1999/07/12 21:05:12 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 1.2 1999/07/01 08:16:03 keil - * teles3c ---> hfcscard - * - * + * This file is (c) under GNU PUBLIC LICENSE * */ @@ -34,7 +15,7 @@ extern const char *CardType[]; -static const char *hfcs_revision = "$Revision: 1.6 $"; +static const char *hfcs_revision = "$Revision: 1.7 $"; static void hfcs_interrupt(int intno, void *dev_id, struct pt_regs *regs) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/hisax.h linux/drivers/isdn/hisax/hisax.h --- v2.4.0-test5/linux/drivers/isdn/hisax/hisax.h Wed Apr 26 16:34:07 2000 +++ linux/drivers/isdn/hisax/hisax.h Sun Aug 6 12:43:41 2000 @@ -1,146 +1,8 @@ -/* $Id: hisax.h,v 2.42 2000/04/09 19:02:44 keil Exp $ - - * Basic declarations, defines and prototypes - * - * $Log: hisax.h,v $ - * Revision 2.42 2000/04/09 19:02:44 keil - * retry pump modulation settings if it fails - * - * Revision 2.41 2000/02/26 00:35:13 keil - * Fix skb freeing in interrupt context - * - * Revision 2.40 2000/01/20 19:51:46 keil - * Fix AddTimer message - * Change CONFIG defines - * - * Revision 2.39 1999/11/18 00:00:43 werner - * - * Added support for HFC-S+ and HFC-SP cards - * - * Revision 2.38 1999/11/14 23:37:03 keil - * new ISA memory mapped IO - * - * Revision 2.37 1999/10/14 20:25:28 keil - * add a statistic for error monitoring - * - * Revision 2.36 1999/10/10 20:16:15 werner - * - * Added variable to hfcpci union. - * - * Revision 2.35 1999/09/04 06:35:09 keil - * Winbond W6692 support - * - * Revision 2.34 1999/08/25 17:00:04 keil - * Make ISAR V32bis modem running - * Make LL->HL interface open for additional commands - * - * Revision 2.33 1999/08/05 20:43:16 keil - * ISAR analog modem support - * - * Revision 2.31 1999/07/21 14:46:11 keil - * changes from EICON certification - * - * Revision 2.30 1999/07/14 12:38:38 werner - * Added changes for echo channel handling - * - * Revision 2.29 1999/07/12 21:05:14 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 2.28 1999/07/05 23:51:46 werner - * Allow limiting of available HiSax B-chans per card. Controlled by hisaxctrl - * hisaxctrl id 10 - * - * Revision 2.27 1999/07/01 08:11:38 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 2.26 1998/11/15 23:54:45 keil - * changes from 2.0 - * - * Revision 2.25 1998/09/30 22:28:42 keil - * More work for ISAR support - * - * Revision 2.24 1998/08/20 13:50:39 keil - * More support for hybrid modem (not working yet) - * - * Revision 2.23 1998/08/13 23:36:31 keil - * HiSax 3.1 - don't work stable with current LinkLevel +/* $Id: hisax.h,v 2.48 2000/07/04 10:24:32 keil Exp $ * - * Revision 2.22 1998/07/15 15:01:28 calle - * Support for AVM passive PCMCIA cards: - * A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0 - * - * Revision 2.21 1998/05/25 14:10:05 keil - * HiSax 3.0 - * X.75 and leased are working again. - * - * Revision 2.20 1998/05/25 12:57:57 keil - * HiSax golden code from certification, Don't use !!! - * No leased lines, no X75, but many changes. - * - * Revision 2.19 1998/04/15 16:39:15 keil - * Add S0Box and Teles PCI support - * - * Revision 2.18 1998/03/26 07:10:04 paul - * The jumpmatrix table in struct Fsm was an array of "int". This is not - * large enough for pointers to functions on Linux/Alpha (instant crash - * on "insmod hisax). Now there is a typedef for the pointer to function. - * This also prevents warnings about "incompatible pointer types". - * - * Revision 2.17 1998/03/19 13:18:43 keil - * Start of a CAPI like interface for supplementary Service - * first service: SUSPEND - * - * Revision 2.16 1998/03/09 23:19:25 keil - * Changes for PCMCIA - * - * Revision 2.14 1998/02/11 17:28:04 keil - * Niccy PnP/PCI support - * - * Revision 2.13 1998/02/09 18:46:02 keil - * Support for Sedlbauer PCMCIA (Marcus Niemann) - * - * Revision 2.12 1998/02/03 23:31:30 keil - * add AMD7930 support - * - * Revision 2.11 1998/02/02 13:33:00 keil - * New card support - * - * Revision 2.10 1997/11/08 21:37:52 keil - * new l1 init;new Compaq card - * - * Revision 2.9 1997/11/06 17:09:09 keil - * New 2.1 init code - * - * Revision 2.8 1997/10/29 19:04:13 keil - * new L1; changes for 2.1 - * - * Revision 2.7 1997/10/10 20:56:47 fritz - * New HL interface. - * - * Revision 2.6 1997/09/11 17:25:51 keil - * Add new cards - * - * Revision 2.5 1997/08/03 14:36:31 keil - * Implement RESTART procedure - * - * Revision 2.4 1997/07/31 19:25:20 keil - * PTP_DATA_LINK support - * - * Revision 2.3 1997/07/31 11:50:17 keil - * ONE TEI and FIXED TEI handling - * - * Revision 2.2 1997/07/30 17:13:02 keil - * more changes for 'One TEI per card' - * - * Revision 2.1 1997/07/27 21:45:13 keil - * new main structures - * - * Revision 2.0 1997/06/26 11:06:27 keil - * New card and L1 interface. - * Eicon.Diehl Diva and Dynalink IS64PH support + * Basic declarations, defines and prototypes * - * old changes removed KKe + * This file is (c) under GNU PUBLIC LICENSE * */ #include diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/hscx.c linux/drivers/isdn/hisax/hscx.c --- v2.4.0-test5/linux/drivers/isdn/hisax/hscx.c Sat Feb 26 22:31:46 2000 +++ linux/drivers/isdn/hisax/hscx.c Sun Aug 6 12:43:41 2000 @@ -1,64 +1,10 @@ -/* $Id: hscx.c,v 1.18 2000/02/26 00:35:13 keil Exp $ - +/* $Id: hscx.c,v 1.19 2000/06/26 08:59:13 keil Exp $ + * * hscx.c HSCX specific routines * * Author Karsten Keil (keil@isdn4linux.de) * - * - * $Log: hscx.c,v $ - * Revision 1.18 2000/02/26 00:35:13 keil - * Fix skb freeing in interrupt context - * - * Revision 1.17 1999/07/01 08:11:41 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 1.16 1998/11/15 23:54:48 keil - * changes from 2.0 - * - * Revision 1.15 1998/08/20 13:50:42 keil - * More support for hybrid modem (not working yet) - * - * Revision 1.14 1998/08/13 23:36:33 keil - * HiSax 3.1 - don't work stable with current LinkLevel - * - * Revision 1.13 1998/06/26 22:03:28 keil - * send flags between hdlc frames - * - * Revision 1.12 1998/06/09 18:26:01 keil - * PH_DEACTIVATE B-channel every time signaled to higher layer - * - * Revision 1.11 1998/05/25 14:10:07 keil - * HiSax 3.0 - * X.75 and leased are working again. - * - * Revision 1.10 1998/05/25 12:57:59 keil - * HiSax golden code from certification, Don't use !!! - * No leased lines, no X75, but many changes. - * - * Revision 1.9 1998/04/15 16:45:33 keil - * new init code - * - * Revision 1.8 1998/03/19 13:16:24 keil - * fix the correct release of the hscx - * - * Revision 1.7 1998/02/12 23:07:36 keil - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 1.6 1998/02/02 13:41:12 keil - * new init - * - * Revision 1.5 1997/11/06 17:09:34 keil - * New 2.1 init code - * - * Revision 1.4 1997/10/29 19:01:06 keil - * changes for 2.1 - * - * Revision 1.3 1997/07/27 21:38:34 keil - * new B-channel interface - * - * Revision 1.2 1997/06/26 11:16:17 keil - * first version - * + * This file is (c) under GNU PUBLIC LICENSE * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/hscx.h linux/drivers/isdn/hisax/hscx.h --- v2.4.0-test5/linux/drivers/isdn/hisax/hscx.h Wed Feb 16 17:03:52 2000 +++ linux/drivers/isdn/hisax/hscx.h Sun Aug 6 12:43:41 2000 @@ -1,23 +1,10 @@ -/* $Id: hscx.h,v 1.5 1999/12/23 15:09:32 keil Exp $ - +/* $Id: hscx.h,v 1.6 2000/06/26 08:59:13 keil Exp $ + * * hscx.h HSCX specific defines * * Author Karsten Keil (keil@isdn4linux.de) * - * - * $Log: hscx.h,v $ - * Revision 1.5 1999/12/23 15:09:32 keil - * change email - * - * Revision 1.4 1998/04/15 16:45:34 keil - * new init code - * - * Revision 1.3 1997/07/27 21:38:35 keil - * new B-channel interface - * - * Revision 1.2 1997/06/26 11:16:18 keil - * first version - * + * This file is (c) under GNU PUBLIC LICENSE * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/hscx_irq.c linux/drivers/isdn/hisax/hscx_irq.c --- v2.4.0-test5/linux/drivers/isdn/hisax/hscx_irq.c Sat Feb 26 22:31:46 2000 +++ linux/drivers/isdn/hisax/hscx_irq.c Sun Aug 6 12:43:41 2000 @@ -1,53 +1,12 @@ -/* $Id: hscx_irq.c,v 1.14 2000/02/26 00:35:13 keil Exp $ - +/* $Id: hscx_irq.c,v 1.15 2000/06/26 08:59:13 keil Exp $ + * * hscx_irq.c low level b-channel stuff for Siemens HSCX * * Author Karsten Keil (keil@isdn4linux.de) * * This is an include file for fast inline IRQ stuff * - * $Log: hscx_irq.c,v $ - * Revision 1.14 2000/02/26 00:35:13 keil - * Fix skb freeing in interrupt context - * - * Revision 1.13 1999/10/14 20:25:28 keil - * add a statistic for error monitoring - * - * Revision 1.12 1999/07/01 08:11:42 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 1.11 1998/11/15 23:54:49 keil - * changes from 2.0 - * - * Revision 1.10 1998/08/13 23:36:35 keil - * HiSax 3.1 - don't work stable with current LinkLevel - * - * Revision 1.9 1998/06/24 14:44:51 keil - * Fix recovery of TX IRQ loss - * - * Revision 1.8 1998/04/10 10:35:22 paul - * fixed (silly?) warnings from egcs on Alpha. - * - * Revision 1.7 1998/02/12 23:07:37 keil - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 1.6 1997/10/29 19:01:07 keil - * changes for 2.1 - * - * Revision 1.5 1997/10/01 09:21:35 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.4 1997/08/15 17:48:02 keil - * cosmetic - * - * Revision 1.3 1997/07/27 21:38:36 keil - * new B-channel interface - * - * Revision 1.2 1997/06/26 11:16:19 keil - * first version - * + * This file is (c) under GNU PUBLIC LICENSE * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/ipac.h linux/drivers/isdn/hisax/ipac.h --- v2.4.0-test5/linux/drivers/isdn/hisax/ipac.h Wed Feb 16 17:03:52 2000 +++ linux/drivers/isdn/hisax/ipac.h Sun Aug 6 12:43:41 2000 @@ -1,24 +1,10 @@ -/* $Id: ipac.h,v 1.4 1999/12/23 15:09:32 keil Exp $ - +/* $Id: ipac.h,v 1.5 2000/06/26 08:59:13 keil Exp $ + * * ipac.h IPAC specific defines * * Author Karsten Keil (keil@isdn4linux.de) * - * - * $Log: ipac.h,v $ - * Revision 1.4 1999/12/23 15:09:32 keil - * change email - * - * Revision 1.3 1998/04/15 16:48:09 keil - * IPAC_ATX added - * - * Revision 1.2 1997/10/29 18:51:21 keil - * New files - * - * Revision 1.1.2.1 1997/10/17 22:10:48 keil - * new files on 2.0 - * - * + * This file is (c) under GNU PUBLIC LICENSE * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/isac.c linux/drivers/isdn/hisax/isac.c --- v2.4.0-test5/linux/drivers/isdn/hisax/isac.c Sat Feb 26 22:31:46 2000 +++ linux/drivers/isdn/hisax/isac.c Sun Aug 6 12:43:41 2000 @@ -1,5 +1,5 @@ -/* $Id: isac.c,v 1.25 2000/02/26 00:35:13 keil Exp $ - +/* $Id: isac.c,v 1.26 2000/06/26 08:59:13 keil Exp $ + * * isac.c ISAC specific routines * * Author Karsten Keil (keil@isdn4linux.de) @@ -7,85 +7,6 @@ * This file is (c) under GNU PUBLIC LICENSE * For changes and modifications please read * ../../../Documentation/isdn/HiSax.cert - * - * $Log: isac.c,v $ - * Revision 1.25 2000/02/26 00:35:13 keil - * Fix skb freeing in interrupt context - * - * Revision 1.24 1999/10/14 20:25:28 keil - * add a statistic for error monitoring - * - * Revision 1.23 1999/08/25 16:50:52 keil - * Fix bugs which cause 2.3.14 hangs (waitqueue init) - * - * Revision 1.22 1999/08/09 19:04:40 keil - * Fix race condition - Thanks to Christer Weinigel - * - * Revision 1.21 1999/07/12 21:05:17 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 1.20 1999/07/09 08:23:06 keil - * Fix ISAC lost TX IRQ handling - * - * Revision 1.19 1999/07/01 08:11:43 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 1.18 1998/11/15 23:54:51 keil - * changes from 2.0 - * - * Revision 1.17 1998/08/13 23:36:37 keil - * HiSax 3.1 - don't work stable with current LinkLevel - * - * Revision 1.16 1998/05/25 12:58:01 keil - * HiSax golden code from certification, Don't use !!! - * No leased lines, no X75, but many changes. - * - * Revision 1.15 1998/04/15 16:45:32 keil - * new init code - * - * Revision 1.14 1998/04/10 10:35:26 paul - * fixed (silly?) warnings from egcs on Alpha. - * - * Revision 1.13 1998/03/07 22:57:01 tsbogend - * made HiSax working on Linux/Alpha - * - * Revision 1.12 1998/02/12 23:07:40 keil - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 1.11 1998/02/09 10:54:49 keil - * fixes for leased mode - * - * Revision 1.10 1998/02/02 13:37:37 keil - * new init - * - * Revision 1.9 1997/11/06 17:09:07 keil - * New 2.1 init code - * - * Revision 1.8 1997/10/29 19:00:03 keil - * new layer1,changes for 2.1 - * - * Revision 1.7 1997/10/01 09:21:37 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.6 1997/08/15 17:47:08 keil - * avoid oops because a uninitialised timer - * - * Revision 1.5 1997/08/07 17:48:49 keil - * fix wrong parenthesis - * - * Revision 1.4 1997/07/30 17:11:59 keil - * fixed Timer3 - * - * Revision 1.3 1997/07/27 21:37:40 keil - * T3 implemented; supervisor l1timer; B-channel TEST_LOOP - * - * Revision 1.2 1997/06/26 11:16:15 keil - * first version - * - * */ #define __NO_VERSION__ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/isac.h linux/drivers/isdn/hisax/isac.h --- v2.4.0-test5/linux/drivers/isdn/hisax/isac.h Wed Feb 16 17:03:52 2000 +++ linux/drivers/isdn/hisax/isac.h Sun Aug 6 12:43:41 2000 @@ -1,27 +1,10 @@ -/* $Id: isac.h,v 1.6 1999/12/23 15:09:32 keil Exp $ - +/* $Id: isac.h,v 1.7 2000/06/26 08:59:13 keil Exp $ + * * isac.h ISAC specific defines * * Author Karsten Keil (keil@isdn4linux.de) * - * - * $Log: isac.h,v $ - * Revision 1.6 1999/12/23 15:09:32 keil - * change email - * - * Revision 1.5 1998/05/25 12:58:03 keil - * HiSax golden code from certification, Don't use !!! - * No leased lines, no X75, but many changes. - * - * Revision 1.4 1997/10/29 19:09:34 keil - * new L1 - * - * Revision 1.3 1997/07/27 21:37:41 keil - * T3 implemented; supervisor l1timer; B-channel TEST_LOOP - * - * Revision 1.2 1997/06/26 11:16:16 keil - * first version - * + * This file is (c) under GNU PUBLIC LICENSE * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/isar.c linux/drivers/isdn/hisax/isar.c --- v2.4.0-test5/linux/drivers/isdn/hisax/isar.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/isdn/hisax/isar.c Sun Aug 6 12:43:41 2000 @@ -1,45 +1,10 @@ -/* $Id: isar.c,v 1.11 2000/04/09 19:02:44 keil Exp $ - +/* $Id: isar.c,v 1.15 2000/06/26 08:59:13 keil Exp $ + * * isar.c ISAR (Siemens PSB 7110) specific routines * * Author Karsten Keil (keil@isdn4linux.de) * - * - * $Log: isar.c,v $ - * Revision 1.11 2000/04/09 19:02:44 keil - * retry pump modulation settings if it fails - * - * Revision 1.10 2000/02/26 00:35:13 keil - * Fix skb freeing in interrupt context - * - * Revision 1.9 2000/01/20 19:47:45 keil - * Add Fax Class 1 support - * - * Revision 1.8 1999/12/19 13:00:56 keil - * Fix races in setting a new mode - * - * Revision 1.7 1999/10/14 20:25:29 keil - * add a statistic for error monitoring - * - * Revision 1.6 1999/08/31 11:20:20 paul - * various spelling corrections (new checksums may be needed, Karsten!) - * - * Revision 1.5 1999/08/25 16:59:55 keil - * Make ISAR V32bis modem running - * Make LL->HL interface open for additional commands - * - * Revision 1.4 1999/08/05 20:43:18 keil - * ISAR analog modem support - * - * Revision 1.3 1999/07/01 08:11:45 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 1.2 1998/11/15 23:54:53 keil - * changes from 2.0 - * - * Revision 1.1 1998/08/13 23:33:47 keil - * First version, only init - * + * This file is (c) under GNU PUBLIC LICENSE * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/isar.h linux/drivers/isdn/hisax/isar.h --- v2.4.0-test5/linux/drivers/isdn/hisax/isar.h Wed Feb 16 17:03:52 2000 +++ linux/drivers/isdn/hisax/isar.h Sun Aug 6 12:43:41 2000 @@ -1,32 +1,10 @@ -/* $Id: isar.h,v 1.7 2000/01/20 19:47:45 keil Exp $ +/* $Id: isar.h,v 1.9 2000/06/26 08:59:13 keil Exp $ + * * isar.h ISAR (Siemens PSB 7110) specific defines * * Author Karsten Keil (keil@isdn4linux.de) * - * - * $Log: isar.h,v $ - * Revision 1.7 2000/01/20 19:47:45 keil - * Add Fax Class 1 support - * - * Revision 1.6 1999/10/14 20:25:29 keil - * add a statistic for error monitoring - * - * Revision 1.5 1999/08/25 16:59:59 keil - * Make ISAR V32bis modem running - * Make LL->HL interface open for additional commands - * - * Revision 1.4 1999/08/05 20:43:20 keil - * ISAR analog modem support - * - * Revision 1.3 1999/07/01 08:11:46 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 1.2 1998/11/15 23:54:54 keil - * changes from 2.0 - * - * Revision 1.1 1998/08/13 23:33:48 keil - * First version, only init - * + * This file is (c) under GNU PUBLIC LICENSE * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/isdnl1.c linux/drivers/isdn/hisax/isdnl1.c --- v2.4.0-test5/linux/drivers/isdn/hisax/isdnl1.c Wed Feb 16 17:03:52 2000 +++ linux/drivers/isdn/hisax/isdnl1.c Sun Aug 6 12:43:41 2000 @@ -1,5 +1,5 @@ -/* $Id: isdnl1.c,v 2.37 2000/01/20 19:51:46 keil Exp $ - +/* $Id: isdnl1.c,v 2.39 2000/06/26 08:59:13 keil Exp $ + * * isdnl1.c common low level stuff for Siemens Chipsetbased isdn cards * based on the teles driver from Jan den Ouden * @@ -13,136 +13,9 @@ * Fritz Elfert * Beat Doebeli * - * - * $Log: isdnl1.c,v $ - * Revision 2.37 2000/01/20 19:51:46 keil - * Fix AddTimer message - * Change CONFIG defines - * - * Revision 2.36 1999/08/25 16:50:57 keil - * Fix bugs which cause 2.3.14 hangs (waitqueue init) - * - * Revision 2.35 1999/08/22 20:27:07 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 2.34 1999/07/09 13:50:15 keil - * remove unused variable - * - * Revision 2.33 1999/07/09 13:34:33 keil - * remove debug code - * - * Revision 2.32 1999/07/01 08:11:47 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 2.31 1998/11/15 23:54:56 keil - * changes from 2.0 - * - * Revision 2.30 1998/09/30 22:27:00 keil - * Add init of l1.Flags - * - * Revision 2.29 1998/09/27 23:54:43 keil - * cosmetics - * - * Revision 2.28 1998/09/27 12:52:23 keil - * Fix against segfault, if the driver cannot allocate an IRQ channel - * - * Revision 2.27 1998/08/13 23:36:39 keil - * HiSax 3.1 - don't work stable with current LinkLevel - * - * Revision 2.26 1998/07/15 15:01:31 calle - * Support for AVM passive PCMCIA cards: - * A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0 - * - * Revision 2.25 1998/05/25 14:10:09 keil - * HiSax 3.0 - * X.75 and leased are working again. - * - * Revision 2.24 1998/05/25 12:58:04 keil - * HiSax golden code from certification, Don't use !!! - * No leased lines, no X75, but many changes. - * - * Revision 2.22 1998/04/15 16:40:13 keil - * Add S0Box and Teles PCI support - * Fix cardnr overwrite bug - * - * Revision 2.21 1998/04/10 10:35:28 paul - * fixed (silly?) warnings from egcs on Alpha. - * - * Revision 2.20 1998/03/09 23:19:27 keil - * Changes for PCMCIA - * - * Revision 2.18 1998/02/12 23:07:42 keil - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 2.17 1998/02/11 17:28:07 keil - * Niccy PnP/PCI support - * - * Revision 2.16 1998/02/09 18:46:08 keil - * Support for Sedlbauer PCMCIA (Marcus Niemann) - * - * Revision 2.15 1998/02/09 10:54:51 keil - * fixes for leased mode - * - * Revision 2.14 1998/02/03 23:31:31 keil - * add AMD7930 support - * - * Revision 2.13 1998/02/02 13:33:02 keil - * New card support - * - * Revision 2.12 1998/01/31 21:41:48 keil - * changes for newer 2.1 kernels - * - * Revision 2.11 1997/11/12 15:01:23 keil - * COMPAQ_ISA changes - * - * Revision 2.10 1997/11/08 21:35:48 keil - * new l1 init - * - * Revision 2.9 1997/11/06 17:09:18 keil - * New 2.1 init code - * - * Revision 2.8 1997/10/29 19:00:05 keil - * new layer1,changes for 2.1 - * - * Revision 2.7 1997/10/10 20:56:50 fritz - * New HL interface. - * - * Revision 2.6 1997/09/12 10:05:16 keil - * ISDN_CTRL_DEBUG define - * - * Revision 2.5 1997/09/11 17:24:45 keil - * Add new cards - * - * Revision 2.4 1997/08/15 17:47:09 keil - * avoid oops because a uninitialised timer - * - * Revision 2.3 1997/08/01 11:16:40 keil - * cosmetics - * - * Revision 2.2 1997/07/30 17:11:08 keil - * L1deactivated exported - * - * Revision 2.1 1997/07/27 21:35:38 keil - * new layer1 interface - * - * Revision 2.0 1997/06/26 11:02:53 keil - * New Layer and card interface - * - * Revision 1.15 1997/05/27 15:17:55 fritz - * Added changes for recent 2.1.x kernels: - * changed return type of isdn_close - * queue_task_* -> queue_task - * clear/set_bit -> test_and_... where apropriate. - * changed type of hard_header_cache parameter. - * - * old changes removed KKe - * */ -const char *l1_revision = "$Revision: 2.37 $"; +const char *l1_revision = "$Revision: 2.39 $"; #define __NO_VERSION__ #include "hisax.h" diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/isdnl1.h linux/drivers/isdn/hisax/isdnl1.h --- v2.4.0-test5/linux/drivers/isdn/hisax/isdnl1.h Sun May 23 10:03:41 1999 +++ linux/drivers/isdn/hisax/isdnl1.h Sun Aug 6 12:43:41 2000 @@ -1,34 +1,8 @@ -/* $Id: isdnl1.h,v 2.8 1998/11/15 23:54:59 keil Exp $ - - * $Log: isdnl1.h,v $ - * Revision 2.8 1998/11/15 23:54:59 keil - * changes from 2.0 +/* $Id: isdnl1.h,v 2.9 2000/06/26 08:59:13 keil Exp $ * - * Revision 2.7 1998/09/30 22:21:55 keil - * cosmetics - * - * Revision 2.6 1998/05/25 12:58:06 keil - * HiSax golden code from certification, Don't use !!! - * No leased lines, no X75, but many changes. - * - * Revision 2.5 1998/02/02 13:36:58 keil - * more debug - * - * Revision 2.4 1997/11/08 21:35:49 keil - * new l1 init - * - * Revision 2.3 1997/10/29 19:07:53 keil - * changes for 2.1 - * - * Revision 2.2 1997/07/30 17:11:09 keil - * L1deactivated exported - * - * Revision 2.1 1997/07/27 21:43:58 keil - * new l1 interface - * - * Revision 2.0 1997/06/26 11:02:55 keil - * New Layer and card interface + * Layer 1 defines * + * This file is (c) under GNU PUBLIC LICENSE * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/isdnl2.c linux/drivers/isdn/hisax/isdnl2.c --- v2.4.0-test5/linux/drivers/isdn/hisax/isdnl2.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/isdn/hisax/isdnl2.c Sun Aug 6 12:43:41 2000 @@ -1,5 +1,5 @@ -/* $Id: isdnl2.c,v 2.22 2000/04/12 20:28:37 keil Exp $ - +/* $Id: isdnl2.c,v 2.23 2000/06/26 08:59:13 keil Exp $ + * * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden * @@ -10,87 +10,12 @@ * Thanks to Jan den Ouden * Fritz Elfert * - * $Log: isdnl2.c,v $ - * Revision 2.22 2000/04/12 20:28:37 keil - * a I frame may be contain zero information bytes - * - * Revision 2.21 2000/04/12 16:41:01 kai - * fix max iframe size - * fix bug in multicasting DL_RELEASE_IND - * - * Revision 2.20 1999/08/25 16:52:04 keil - * Make gcc on AXP happy - * - * Revision 2.19 1999/08/05 20:40:26 keil - * Fix interlayer communication - * - * Revision 2.18 1999/07/21 14:46:16 keil - * changes from EICON certification - * - * Revision 2.17 1999/07/01 08:11:50 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 2.16 1998/11/15 23:55:01 keil - * changes from 2.0 - * - * Revision 2.15 1998/08/13 23:36:42 keil - * HiSax 3.1 - don't work stable with current LinkLevel - * - * Revision 2.14 1998/06/19 15:19:18 keil - * fix LAPB tx_cnt for none I-frames - * - * Revision 2.13 1998/06/18 23:17:20 keil - * LAPB bugfix - * - * Revision 2.12 1998/05/25 14:10:12 keil - * HiSax 3.0 - * X.75 and leased are working again. - * - * Revision 2.11 1998/05/25 12:58:08 keil - * HiSax golden code from certification, Don't use !!! - * No leased lines, no X75, but many changes. - * - * Revision 2.9 1998/04/10 10:35:30 paul - * fixed (silly?) warnings from egcs on Alpha. - * - * Revision 2.8 1998/03/07 22:57:04 tsbogend - * made HiSax working on Linux/Alpha - * - * Revision 2.7 1998/02/12 23:07:47 keil - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 2.6 1998/02/02 13:36:15 keil - * bugfix X.75 win calculation - * - * Revision 2.5 1997/11/06 17:09:22 keil - * New 2.1 init code - * - * Revision 2.4 1997/10/29 19:02:01 keil - * new LL interface - * - * Revision 2.3 1997/10/01 09:21:39 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 2.2 1997/07/31 11:49:05 keil - * Error handling for no TEI assign - * - * Revision 2.1 1997/07/27 21:34:38 keil - * cosmetics - * - * Revision 2.0 1997/06/26 11:07:29 keil - * New q.921 and X.75 Layer2 - * - * - * Old log removed KKe - * */ #define __NO_VERSION__ #include "hisax.h" #include "isdnl2.h" -const char *l2_revision = "$Revision: 2.22 $"; +const char *l2_revision = "$Revision: 2.23 $"; static void l2m_debug(struct FsmInst *fi, char *fmt, ...); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/isdnl2.h linux/drivers/isdn/hisax/isdnl2.h --- v2.4.0-test5/linux/drivers/isdn/hisax/isdnl2.h Thu May 29 21:53:06 1997 +++ linux/drivers/isdn/hisax/isdnl2.h Sun Aug 6 12:43:41 2000 @@ -1,4 +1,10 @@ -/* isdnl2.h */ +/* $Id: isdnl2.h,v 1.3 2000/06/26 08:59:13 keil Exp $ + * + * Layer 2 defines + * + * This file is (c) under GNU PUBLIC LICENSE + * + */ #define RR 0x01 #define RNR 0x05 diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/isdnl3.c linux/drivers/isdn/hisax/isdnl3.c --- v2.4.0-test5/linux/drivers/isdn/hisax/isdnl3.c Thu May 11 15:30:07 2000 +++ linux/drivers/isdn/hisax/isdnl3.c Sun Aug 6 12:43:41 2000 @@ -1,5 +1,5 @@ -/* $Id: isdnl3.c,v 2.11 2000/04/12 16:41:01 kai Exp $ - +/* $Id: isdnl3.c,v 2.14 2000/06/26 08:59:13 keil Exp $ + * * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden * @@ -10,69 +10,13 @@ * Thanks to Jan den Ouden * Fritz Elfert * - * $Log: isdnl3.c,v $ - * Revision 2.11 2000/04/12 16:41:01 kai - * fix max iframe size - * fix bug in multicasting DL_RELEASE_IND - * - * Revision 2.10 1999/07/21 14:46:19 keil - * changes from EICON certification - * - * Revision 2.9 1999/07/01 08:11:53 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 2.8 1998/11/15 23:55:04 keil - * changes from 2.0 - * - * Revision 2.7 1998/05/25 14:10:15 keil - * HiSax 3.0 - * X.75 and leased are working again. - * - * Revision 2.6 1998/05/25 12:58:11 keil - * HiSax golden code from certification, Don't use !!! - * No leased lines, no X75, but many changes. - * - * Revision 2.5 1998/02/12 23:07:52 keil - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 2.4 1997/11/06 17:09:25 keil - * New 2.1 init code - * - * Revision 2.3 1997/10/29 19:07:53 keil - * changes for 2.1 - * - * Revision 2.2 1997/10/01 09:21:41 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 2.1 1997/08/03 14:36:32 keil - * Implement RESTART procedure - * - * Revision 2.0 1997/07/27 21:15:42 keil - * New Callref based layer3 - * - * Revision 1.11 1997/06/26 11:11:44 keil - * SET_SKBFREE now on creation of a SKB - * - * Revision 1.10 1997/04/06 22:54:16 keil - * Using SKB's - * - * Revision 1.9 1997/03/25 23:11:25 keil - * US NI-1 protocol - * - * Revision 1.8 1997/03/21 18:53:44 keil - * Report no protocol error to syslog too - * - * Remove old logs /KKe - * */ #define __NO_VERSION__ #include "hisax.h" #include "isdnl3.h" #include -const char *l3_revision = "$Revision: 2.11 $"; +const char *l3_revision = "$Revision: 2.14 $"; static struct Fsm l3fsm = diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/isdnl3.h linux/drivers/isdn/hisax/isdnl3.h --- v2.4.0-test5/linux/drivers/isdn/hisax/isdnl3.h Thu Aug 12 09:42:33 1999 +++ linux/drivers/isdn/hisax/isdnl3.h Sun Aug 6 12:43:41 2000 @@ -1,38 +1,6 @@ -/* $Id: isdnl3.h,v 2.5 1999/07/25 16:18:32 keil Exp $ - - * $Log: isdnl3.h,v $ - * Revision 2.5 1999/07/25 16:18:32 keil - * Fix Suspend/Resume - * - * Revision 2.4 1999/07/01 08:11:54 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 2.3 1998/11/15 23:55:06 keil - * changes from 2.0 - * - * Revision 2.2 1998/05/25 14:10:17 keil - * HiSax 3.0 - * X.75 and leased are working again. - * - * Revision 2.1 1998/05/25 12:58:13 keil - * HiSax golden code from certification, Don't use !!! - * No leased lines, no X75, but many changes. - * - * Revision 2.0 1997/07/27 21:15:42 keil - * New Callref based layer3 - * - * Revision 1.4 1997/06/26 11:20:57 keil - * ? - * - * Revision 1.3 1997/04/06 22:54:17 keil - * Using SKB's - * - * Revision 1.2 1997/01/21 22:31:28 keil - * new statemachine; L3 timers - * - * Revision 1.1 1996/10/13 20:03:47 keil - * Initial revision +/* $Id: isdnl3.h,v 2.6 2000/06/26 08:59:13 keil Exp $ * + * This file is (c) under GNU PUBLIC LICENSE * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/isurf.c linux/drivers/isdn/hisax/isurf.c --- v2.4.0-test5/linux/drivers/isdn/hisax/isurf.c Wed Feb 16 17:03:52 2000 +++ linux/drivers/isdn/hisax/isurf.c Sun Aug 6 12:43:41 2000 @@ -1,38 +1,10 @@ -/* $Id: isurf.c,v 1.8 1999/12/19 13:09:42 keil Exp $ - +/* $Id: isurf.c,v 1.9 2000/06/26 08:59:13 keil Exp $ + * * isurf.c low level stuff for Siemens I-Surf/I-Talk cards * * Author Karsten Keil (keil@isdn4linux.de) * - * $Log: isurf.c,v $ - * Revision 1.8 1999/12/19 13:09:42 keil - * changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for - * signal proof delays - * - * Revision 1.7 1999/11/14 23:37:03 keil - * new ISA memory mapped IO - * - * Revision 1.6 1999/09/04 06:20:06 keil - * Changes from kernel set_current_state() - * - * Revision 1.5 1999/08/25 17:00:02 keil - * Make ISAR V32bis modem running - * Make LL->HL interface open for additional commands - * - * Revision 1.4 1999/08/22 20:27:09 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.3 1999/07/12 21:05:18 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 1.2 1999/07/01 08:07:56 keil - * Initial version - * - * + * This file is (c) under GNU PUBLIC LICENSE * */ @@ -44,7 +16,7 @@ extern const char *CardType[]; -static const char *ISurf_revision = "$Revision: 1.8 $"; +static const char *ISurf_revision = "$Revision: 1.9 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/ix1_micro.c linux/drivers/isdn/hisax/ix1_micro.c --- v2.4.0-test5/linux/drivers/isdn/hisax/ix1_micro.c Thu Nov 11 20:11:38 1999 +++ linux/drivers/isdn/hisax/ix1_micro.c Sun Aug 6 12:43:41 2000 @@ -1,5 +1,5 @@ -/* $Id: ix1_micro.c,v 2.8 1999/07/12 21:05:19 keil Exp $ - +/* $Id: ix1_micro.c,v 2.9 2000/06/26 08:59:13 keil Exp $ + * * ix1_micro.c low level stuff for ITK ix1-micro Rev.2 isdn cards * derived from the original file teles3.c from Karsten Keil * @@ -10,45 +10,6 @@ * Fritz Elfert * Beat Doebeli * - * $Log: ix1_micro.c,v $ - * Revision 2.8 1999/07/12 21:05:19 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 2.7 1998/04/15 16:44:31 keil - * new init code - * - * Revision 2.6 1998/02/11 17:28:09 keil - * Niccy PnP/PCI support - * - * Revision 2.5 1998/02/02 13:29:42 keil - * fast io - * - * Revision 2.4 1997/11/08 21:35:50 keil - * new l1 init - * - * Revision 2.3 1997/11/06 17:09:35 keil - * New 2.1 init code - * - * Revision 2.2 1997/10/29 18:55:51 keil - * changes for 2.1.60 (irq2dev_map) - * - * Revision 2.1 1997/07/27 21:47:09 keil - * new interface structures - * - * Revision 2.0 1997/06/26 11:02:50 keil - * New Layer and card interface - * - * Revision 1.3 1997/04/13 19:54:02 keil - * Change in IRQ check delay for SMP - * - * Revision 1.2 1997/04/06 22:54:21 keil - * Using SKB's - * - * Revision 1.1 1997/01/27 15:43:10 keil - * first version - * - * */ /* @@ -88,7 +49,7 @@ #include "isdnl1.h" extern const char *CardType[]; -const char *ix1_revision = "$Revision: 2.8 $"; +const char *ix1_revision = "$Revision: 2.9 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/jade.c linux/drivers/isdn/hisax/jade.c --- v2.4.0-test5/linux/drivers/isdn/hisax/jade.c Sat Feb 26 22:31:46 2000 +++ linux/drivers/isdn/hisax/jade.c Sun Aug 6 12:43:41 2000 @@ -1,16 +1,10 @@ -/* $Id: jade.c,v 1.3 2000/02/26 00:35:13 keil Exp $ +/* $Id: jade.c,v 1.4 2000/06/26 08:59:14 keil Exp $ * * jade.c JADE stuff (derived from original hscx.c) * * Author Roland Klabunde (R.Klabunde@Berkom.de) * - * $Log: jade.c,v $ - * Revision 1.3 2000/02/26 00:35:13 keil - * Fix skb freeing in interrupt context - * - * Revision 1.2 1999/07/01 08:07:57 keil - * Initial version - * + * This file is (c) under GNU PUBLIC LICENSE * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/jade.h linux/drivers/isdn/hisax/jade.h --- v2.4.0-test5/linux/drivers/isdn/hisax/jade.h Thu Aug 12 09:42:33 1999 +++ linux/drivers/isdn/hisax/jade.h Sun Aug 6 12:43:41 2000 @@ -1,13 +1,9 @@ -/* $Id: jade.h,v 1.2 1999/07/01 08:07:58 keil Exp $ +/* $Id: jade.h,v 1.3 2000/06/26 08:59:14 keil Exp $ * jade.h JADE specific defines * * Author Roland Klabunde (R.Klabunde@Berkom.de) * - * - * $Log: jade.h,v $ - * Revision 1.2 1999/07/01 08:07:58 keil - * Initial version - * + * This file is (c) under GNU PUBLIC LICENSE * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/jade_irq.c linux/drivers/isdn/hisax/jade_irq.c --- v2.4.0-test5/linux/drivers/isdn/hisax/jade_irq.c Sat Feb 26 22:31:46 2000 +++ linux/drivers/isdn/hisax/jade_irq.c Sun Aug 6 12:43:41 2000 @@ -1,16 +1,10 @@ -/* $Id: jade_irq.c,v 1.3 2000/02/26 00:35:13 keil Exp $ +/* $Id: jade_irq.c,v 1.4 2000/06/26 08:59:14 keil Exp $ * * jade_irq.c Low level JADE IRQ stuff (derived from original hscx_irq.c) * * Author Roland Klabunde (R.Klabunde@Berkom.de) * - * $Log: jade_irq.c,v $ - * Revision 1.3 2000/02/26 00:35:13 keil - * Fix skb freeing in interrupt context - * - * Revision 1.2 1999/07/01 08:07:59 keil - * Initial version - * + * This file is (c) under GNU PUBLIC LICENSE * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/l3_1tr6.c linux/drivers/isdn/hisax/l3_1tr6.c --- v2.4.0-test5/linux/drivers/isdn/hisax/l3_1tr6.c Wed Feb 16 17:03:52 2000 +++ linux/drivers/isdn/hisax/l3_1tr6.c Tue Aug 8 09:31:00 2000 @@ -1,5 +1,5 @@ -/* $Id: l3_1tr6.c,v 2.10 2000/01/20 19:42:01 keil Exp $ - +/* $Id: l3_1tr6.c,v 2.11 2000/06/26 08:59:14 keil Exp $ + * * German 1TR6 D-channel protocol * * Author Karsten Keil (keil@isdn4linux.de) @@ -8,51 +8,6 @@ * For changes and modifications please read * ../../../Documentation/isdn/HiSax.cert * - * - * $Log: l3_1tr6.c,v $ - * Revision 2.10 2000/01/20 19:42:01 keil - * Fixed uninitialiesed location - * - * Revision 2.9 1999/07/01 08:11:55 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 2.8 1998/11/15 23:55:08 keil - * changes from 2.0 - * - * Revision 2.7 1998/08/13 23:36:45 keil - * HiSax 3.1 - don't work stable with current LinkLevel - * - * Revision 2.6 1998/05/25 14:10:18 keil - * HiSax 3.0 - * X.75 and leased are working again. - * - * Revision 2.5 1998/05/25 12:58:14 keil - * HiSax golden code from certification, Don't use !!! - * No leased lines, no X75, but many changes. - * - * Revision 2.4 1998/02/12 23:07:57 keil - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 2.3 1997/11/06 17:12:24 keil - * KERN_NOTICE --> KERN_INFO - * - * Revision 2.2 1997/10/29 19:03:00 keil - * changes for 2.1 - * - * Revision 2.1 1997/08/03 15:28:09 keil - * release L3 empty processes - * - * Revision 2.0 1997/07/27 21:15:45 keil - * New Callref based layer3 - * - * Revision 1.12 1997/06/26 11:11:45 keil - * SET_SKBFREE now on creation of a SKB - * - * Revision 1.11 1997/04/06 22:54:18 keil - * Using SKB's - * - * Old Log removed /KKe - * */ #define __NO_VERSION__ @@ -62,7 +17,7 @@ #include extern char *HiSax_getrev(const char *revision); -const char *l3_1tr6_revision = "$Revision: 2.10 $"; +const char *l3_1tr6_revision = "$Revision: 2.11 $"; #define MsgHead(ptr, cref, mty, dis) \ *ptr++ = dis; \ @@ -928,7 +883,7 @@ } else { proc->chan = chan; chan->proc = proc; - proc->para.setup = chan->setup; + memcpy (&proc->para.setup, &chan->setup, sizeof (chan->setup)); proc->callref = cr; } } else { diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/l3_1tr6.h linux/drivers/isdn/hisax/l3_1tr6.h --- v2.4.0-test5/linux/drivers/isdn/hisax/l3_1tr6.h Sun May 23 10:03:41 1999 +++ linux/drivers/isdn/hisax/l3_1tr6.h Sun Aug 6 12:43:41 2000 @@ -1,16 +1,8 @@ -/* $Id: l3_1tr6.h,v 2.1 1998/08/13 23:36:48 keil Exp $ +/* $Id: l3_1tr6.h,v 2.2 2000/06/26 08:59:14 keil Exp $ * * German 1TR6 D-channel protocol defines * - * $Log: l3_1tr6.h,v $ - * Revision 2.1 1998/08/13 23:36:48 keil - * HiSax 3.1 - don't work stable with current LinkLevel - * - * Revision 2.0 1997/07/27 21:15:47 keil - * New Callref based layer3 - * - * Revision 1.1 1996/10/13 20:03:48 keil - * Initial revision + * This file is (c) under GNU PUBLIC LICENSE * */ #ifndef l3_1tr6 diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/l3dss1.c linux/drivers/isdn/hisax/l3dss1.c --- v2.4.0-test5/linux/drivers/isdn/hisax/l3dss1.c Mon Mar 27 08:08:25 2000 +++ linux/drivers/isdn/hisax/l3dss1.c Tue Aug 8 09:31:00 2000 @@ -1,5 +1,5 @@ -/* $Id: l3dss1.c,v 2.24 2000/03/19 15:26:35 kai Exp $ - +/* $Id: l3dss1.c,v 2.29 2000/06/26 08:59:14 keil Exp $ + * * EURO/DSS1 D-channel protocol * * Author Karsten Keil (keil@isdn4linux.de) @@ -12,94 +12,6 @@ * Thanks to Jan den Ouden * Fritz Elfert * - * $Log: l3dss1.c,v $ - * Revision 2.24 2000/03/19 15:26:35 kai - * changed keypad to use specified bearer, instead of always a-law - * - * Revision 2.23 2000/02/26 01:38:14 keil - * Fixes for V.110 encoding LLC from Jens Jakobsen - * - * Revision 2.22 2000/01/20 19:44:20 keil - * Fixed uninitialiesed location - * Fixed redirecting number IE in Setup - * Changes from certification - * option for disabling use of KEYPAD protocol - * - * Revision 2.21 1999/12/19 20:25:17 keil - * fixed LLC for outgoing analog calls - * IE Signal is valid on older local switches - * - * Revision 2.20 1999/10/11 22:16:27 keil - * Suspend/Resume is possible without explicit ID too - * - * Revision 2.19 1999/08/25 16:55:23 keil - * Fix for test case TC10011 - * - * Revision 2.18 1999/08/11 20:54:39 keil - * High layer compatibility is valid in SETUP - * - * Revision 2.17 1999/07/25 16:18:25 keil - * Fix Suspend/Resume - * - * Revision 2.16 1999/07/21 14:46:23 keil - * changes from EICON certification - * - * Revision 2.14 1999/07/09 08:30:08 keil - * cosmetics - * - * Revision 2.13 1999/07/01 08:11:58 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 2.12 1998/11/15 23:55:10 keil - * changes from 2.0 - * - * Revision 2.11 1998/08/13 23:36:51 keil - * HiSax 3.1 - don't work stable with current LinkLevel - * - * Revision 2.10 1998/05/25 14:10:20 keil - * HiSax 3.0 - * X.75 and leased are working again. - * - * Revision 2.9 1998/05/25 12:58:17 keil - * HiSax golden code from certification, Don't use !!! - * No leased lines, no X75, but many changes. - * - * Revision 2.8 1998/03/19 13:18:47 keil - * Start of a CAPI like interface for supplementary Service - * first service: SUSPEND - * - * Revision 2.7 1998/02/12 23:08:01 keil - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 2.6 1998/02/03 23:26:35 keil - * V110 extensions from Thomas Pfeiffer - * - * Revision 2.5 1998/02/02 13:34:28 keil - * Support australian Microlink net and german AOCD - * - * Revision 2.4 1997/11/06 17:12:25 keil - * KERN_NOTICE --> KERN_INFO - * - * Revision 2.3 1997/10/29 19:03:01 keil - * changes for 2.1 - * - * Revision 2.2 1997/08/07 17:44:36 keil - * Fix RESTART - * - * Revision 2.1 1997/08/03 14:36:33 keil - * Implement RESTART procedure - * - * Revision 2.0 1997/07/27 21:15:43 keil - * New Callref based layer3 - * - * Revision 1.17 1997/06/26 11:11:46 keil - * SET_SKBFREE now on creation of a SKB - * - * Revision 1.15 1997/04/17 11:50:48 keil - * pa->loc was undefined, if it was not send by the exchange - * - * Old log removed /KKe - * */ #define __NO_VERSION__ @@ -110,7 +22,7 @@ #include extern char *HiSax_getrev(const char *revision); -const char *dss1_revision = "$Revision: 2.24 $"; +const char *dss1_revision = "$Revision: 2.29 $"; #define EXT_BEARER_CAPS 1 @@ -3169,7 +3081,7 @@ if ((proc = dss1_new_l3_process(st, cr))) { proc->chan = chan; chan->proc = proc; - proc->para.setup = chan->setup; + memcpy (&proc->para.setup, &chan->setup, sizeof (chan->setup)); proc->callref = cr; } } else { diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/l3dss1.h linux/drivers/isdn/hisax/l3dss1.h --- v2.4.0-test5/linux/drivers/isdn/hisax/l3dss1.h Wed Feb 16 17:03:52 2000 +++ linux/drivers/isdn/hisax/l3dss1.h Sun Aug 6 12:43:42 2000 @@ -1,39 +1,14 @@ -/* $Id: l3dss1.h,v 1.8 2000/01/20 19:46:15 keil Exp $ +/* $Id: l3dss1.h,v 1.10 2000/06/26 08:59:14 keil Exp $ * * DSS1 (Euro) D-channel protocol defines * - * $Log: l3dss1.h,v $ - * Revision 1.8 2000/01/20 19:46:15 keil - * Changes from certification - * - * Revision 1.7 1999/07/01 08:12:02 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 1.6 1998/03/19 13:18:50 keil - * Start of a CAPI like interface for supplementary Service - * first service: SUSPEND - * - * Revision 1.5 1998/02/02 13:34:30 keil - * Support australian Microlink net and german AOCD - * - * Revision 1.4 1997/10/29 19:07:54 keil - * changes for 2.1 - * - * Revision 1.3 1997/08/07 17:44:37 keil - * Fix RESTART - * - * Revision 1.2 1997/08/03 14:36:34 keil - * Implement RESTART procedure - * - * Revision 1.1 1997/07/27 21:08:38 keil - * new - * - * + * This file is (c) under GNU PUBLIC LICENSE * */ #ifndef l3dss1_process +#define T302 15000 #define T303 4000 #define T304 30000 #define T305 30000 diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/lmgr.c linux/drivers/isdn/hisax/lmgr.c --- v2.4.0-test5/linux/drivers/isdn/hisax/lmgr.c Thu Aug 12 09:42:33 1999 +++ linux/drivers/isdn/hisax/lmgr.c Sun Aug 6 12:43:42 2000 @@ -1,30 +1,10 @@ -/* $Id: lmgr.c,v 1.6 1999/07/01 08:12:04 keil Exp $ - - * Author Karsten Keil (keil@isdn4linux.de) +/* $Id: lmgr.c,v 1.7 2000/06/26 08:59:14 keil Exp $ * + * Author Karsten Keil (keil@isdn4linux.de) * * Layermanagement module * - * $Log: lmgr.c,v $ - * Revision 1.6 1999/07/01 08:12:04 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 1.5 1998/11/15 23:55:12 keil - * changes from 2.0 - * - * Revision 1.4 1998/05/25 12:58:19 keil - * HiSax golden code from certification, Don't use !!! - * No leased lines, no X75, but many changes. - * - * Revision 1.3 1998/03/07 22:57:06 tsbogend - * made HiSax working on Linux/Alpha - * - * Revision 1.2 1997/10/29 19:09:34 keil - * new L1 - * - * Revision 1.1 1997/06/26 11:17:25 keil - * first version - * + * This file is (c) under GNU PUBLIC LICENSE * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/mic.c linux/drivers/isdn/hisax/mic.c --- v2.4.0-test5/linux/drivers/isdn/hisax/mic.c Thu Nov 11 20:11:38 1999 +++ linux/drivers/isdn/hisax/mic.c Sun Aug 6 12:43:42 2000 @@ -1,38 +1,12 @@ -/* $Id: mic.c,v 1.8 1999/07/12 21:05:20 keil Exp $ - +/* $Id: mic.c,v 1.9 2000/06/26 08:59:14 keil Exp $ + * * mic.c low level stuff for mic cards * * Copyright (C) 1997 * * Author Stephan von Krawczynski * - * - * $Log: mic.c,v $ - * Revision 1.8 1999/07/12 21:05:20 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 1.7 1998/04/15 16:44:32 keil - * new init code - * - * Revision 1.6 1998/02/17 15:39:57 keil - * fix reset problem - * - * Revision 1.5 1998/02/02 13:29:43 keil - * fast io - * - * Revision 1.4 1997/11/08 21:35:51 keil - * new l1 init - * - * Revision 1.3 1997/11/06 17:09:11 keil - * New 2.1 init code - * - * Revision 1.2 1997/10/29 18:51:17 keil - * New files - * - * Revision 1.1.2.1 1997/10/17 22:10:54 keil - * new files on 2.0 - * + * This file is (c) under GNU PUBLIC LICENSE * */ @@ -44,7 +18,7 @@ extern const char *CardType[]; -const char *mic_revision = "$Revision: 1.8 $"; +const char *mic_revision = "$Revision: 1.9 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/netjet.c linux/drivers/isdn/hisax/netjet.c --- v2.4.0-test5/linux/drivers/isdn/hisax/netjet.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/isdn/hisax/netjet.c Sun Aug 6 12:43:42 2000 @@ -1,70 +1,12 @@ -/* $Id: netjet.c,v 1.18 2000/02/26 00:35:13 keil Exp $ - +/* $Id: netjet.c,v 1.20 2000/06/26 08:59:14 keil Exp $ + * * netjet.c low level stuff for Traverse Technologie NETJet ISDN cards * * Author Karsten Keil (keil@isdn4linux.de) * * Thanks to Traverse Technologie Australia for documents and informations * - * $Log: netjet.c,v $ - * Revision 1.18 2000/02/26 00:35:13 keil - * Fix skb freeing in interrupt context - * - * Revision 1.17 1999/12/19 13:09:42 keil - * changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for - * signal proof delays - * - * Revision 1.16 1999/10/14 20:25:29 keil - * add a statistic for error monitoring - * - * Revision 1.15 1999/09/04 06:20:06 keil - * Changes from kernel set_current_state() - * - * Revision 1.14 1999/08/31 11:20:25 paul - * various spelling corrections (new checksums may be needed, Karsten!) - * - * Revision 1.13 1999/08/11 21:01:31 keil - * new PCI codefix - * - * Revision 1.12 1999/08/10 16:02:00 calle - * struct pci_dev changed in 2.3.13. Made the necessary changes. - * - * Revision 1.11 1999/08/07 17:32:00 keil - * Asymetric buffers for improved ping times. Interframe spacing - * fix for NJ<->NJ thoughput. Matt Henderson - www.traverse.com.au - * - * - * Revision 1.10 1999/07/12 21:05:22 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 1.9 1999/07/01 08:12:05 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 1.8 1998/11/15 23:55:14 keil - * changes from 2.0 - * - * Revision 1.7 1998/09/30 22:24:48 keil - * Fix missing line in setstack* - * - * Revision 1.6 1998/08/13 23:36:54 keil - * HiSax 3.1 - don't work stable with current LinkLevel - * - * Revision 1.5 1998/05/25 12:58:21 keil - * HiSax golden code from certification, Don't use !!! - * No leased lines, no X75, but many changes. - * - * Revision 1.4 1998/04/15 16:42:35 keil - * new init code - * new PCI init (2.1.94) - * - * Revision 1.3 1998/02/12 23:08:05 keil - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 1.2 1998/02/02 13:32:06 keil - * New - * - * + * This file is (c) under GNU PUBLIC LICENSE * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/niccy.c linux/drivers/isdn/hisax/niccy.c --- v2.4.0-test5/linux/drivers/isdn/hisax/niccy.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/isdn/hisax/niccy.c Sun Aug 6 12:43:42 2000 @@ -1,5 +1,5 @@ -/* $Id: niccy.c,v 1.10 2000/04/11 11:12:39 keil Exp $ - +/* $Id: niccy.c,v 1.12 2000/06/26 08:59:14 keil Exp $ + * * niccy.c low level stuff for Dr. Neuhaus NICCY PnP and NICCY PCI and * compatible (SAGEM cybermodem) * @@ -7,34 +7,7 @@ * * Thanks to Dr. Neuhaus and SAGEM for informations * - * $Log: niccy.c,v $ - * Revision 1.10 2000/04/11 11:12:39 keil - * cleanup - * - * Revision 1.9 2000/04/09 19:09:19 keil - * Bugfix: reset IRQ enable only valid for PCI version - * - * Revision 1.8 1999/08/11 21:01:33 keil - * new PCI codefix - * - * Revision 1.7 1999/08/10 16:02:04 calle - * struct pci_dev changed in 2.3.13. Made the necessary changes. - * - * Revision 1.6 1999/07/12 21:05:23 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 1.5 1999/07/01 08:12:07 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 1.4 1998/04/16 19:16:48 keil - * need config.h - * - * Revision 1.3 1998/04/15 16:42:59 keil - * new init code - * - * Revision 1.2 1998/02/11 17:31:04 keil - * new file + * This file is (c) under GNU PUBLIC LICENSE * */ @@ -48,7 +21,7 @@ #include extern const char *CardType[]; -const char *niccy_revision = "$Revision: 1.10 $"; +const char *niccy_revision = "$Revision: 1.12 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/q931.c linux/drivers/isdn/hisax/q931.c --- v2.4.0-test5/linux/drivers/isdn/hisax/q931.c Mon Mar 27 08:08:25 2000 +++ linux/drivers/isdn/hisax/q931.c Sun Aug 6 12:43:42 2000 @@ -1,9 +1,11 @@ -/* $Id: q931.c,v 1.8 2000/03/21 23:53:22 kai Exp $ - +/* $Id: q931.c,v 1.10 2000/06/26 08:59:14 keil Exp $ + * * q931.c code to decode ITU Q.931 call control messages * * Author Jan den Ouden * + * This file is (c) under GNU PUBLIC LICENSE + * * Changelog * * Pauline Middelink general improvements @@ -11,33 +13,6 @@ * Beat Doebeli cause texts, display information element * * Karsten Keil cause texts, display information element for 1TR6 - * - * - * $Log: q931.c,v $ - * Revision 1.8 2000/03/21 23:53:22 kai - * fix backwards compatibility - * - * Revision 1.7 1998/11/15 23:55:17 keil - * changes from 2.0 - * - * Revision 1.6 1997/07/27 21:09:44 keil - * move functions to isdnl3.c - * - * Revision 1.5 1997/04/06 22:56:43 keil - * Some cosmetic changes - * - * Revision 1.4 1997/02/09 00:29:11 keil - * new interface handling, one interface per card - * - * Revision 1.3 1997/01/21 22:24:59 keil - * cleanups - * - * Revision 1.2 1996/10/27 22:12:45 keil - * reporting unknown level 3 protocol ids - * - * Revision 1.1 1996/10/13 20:04:56 keil - * Initial revision - * * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/rawhdlc.c linux/drivers/isdn/hisax/rawhdlc.c --- v2.4.0-test5/linux/drivers/isdn/hisax/rawhdlc.c Wed Feb 16 17:03:52 2000 +++ linux/drivers/isdn/hisax/rawhdlc.c Sun Aug 6 12:43:42 2000 @@ -1,10 +1,11 @@ -/* $Id: rawhdlc.c,v 1.4 1999/12/23 15:09:32 keil Exp $ - +/* $Id: rawhdlc.c,v 1.5 2000/06/26 08:59:14 keil Exp $ + * * rawhdlc.c support routines for cards that don't support HDLC * * Author Karsten Keil (keil@isdn4linux.de) * Brent Baccala * + * This file is (c) under GNU PUBLIC LICENSE * * Some passive ISDN cards, such as the Traverse NETJet and the AMD 7930, * don't perform HDLC encapsulation over the B channel. Drivers for diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/rawhdlc.h linux/drivers/isdn/hisax/rawhdlc.h --- v2.4.0-test5/linux/drivers/isdn/hisax/rawhdlc.h Wed Apr 1 16:21:02 1998 +++ linux/drivers/isdn/hisax/rawhdlc.h Sun Aug 6 12:43:42 2000 @@ -1,8 +1,10 @@ -/* $Id: rawhdlc.h,v 1.2 1998/02/09 10:53:53 keil Exp $ - +/* $Id: rawhdlc.h,v 1.3 2000/06/26 08:59:14 keil Exp $ + * * rawhdlc.h support routines for cards that don't support HDLC * * Author Brent Baccala + * + * This file is (c) under GNU PUBLIC LICENSE * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/s0box.c linux/drivers/isdn/hisax/s0box.c --- v2.4.0-test5/linux/drivers/isdn/hisax/s0box.c Thu Nov 11 20:11:38 1999 +++ linux/drivers/isdn/hisax/s0box.c Sun Aug 6 12:43:42 2000 @@ -1,9 +1,10 @@ -/* $Id: s0box.c,v 2.2 1999/07/12 21:05:25 keil Exp $ - +/* $Id: s0box.c,v 2.3 2000/06/26 08:59:14 keil Exp $ + * * s0box.c low level stuff for Creatix S0BOX * * Author S0BOX specific stuff: Enrik Berkhan (enrik@starfleet.inka.de) * + * This file is (c) under GNU PUBLIC LICENSE * */ #define __NO_VERSION__ @@ -13,7 +14,7 @@ #include "isdnl1.h" extern const char *CardType[]; -const char *s0box_revision = "$Revision: 2.2 $"; +const char *s0box_revision = "$Revision: 2.3 $"; static inline void writereg(unsigned int padr, signed int addr, u_char off, u_char val) { diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/saphir.c linux/drivers/isdn/hisax/saphir.c --- v2.4.0-test5/linux/drivers/isdn/hisax/saphir.c Thu May 11 15:30:07 2000 +++ linux/drivers/isdn/hisax/saphir.c Sun Aug 6 12:43:42 2000 @@ -1,27 +1,12 @@ -/* $Id: saphir.c,v 1.5 1999/12/19 13:09:42 keil Exp $ - +/* $Id: saphir.c,v 1.7 2000/06/26 08:59:14 keil Exp $ + * * saphir.c low level stuff for HST Saphir 1 * * Author Karsten Keil (keil@isdn4linux.de) * * Thanks to HST High Soft Tech GmbH * - * - * $Log: saphir.c,v $ - * Revision 1.5 1999/12/19 13:09:42 keil - * changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for - * signal proof delays - * - * Revision 1.4 1999/09/04 06:20:06 keil - * Changes from kernel set_current_state() - * - * Revision 1.3 1999/07/12 21:05:26 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 1.2 1999/07/01 08:07:55 keil - * Initial version - * + * This file is (c) under GNU PUBLIC LICENSE * */ @@ -33,7 +18,7 @@ #include "isdnl1.h" extern const char *CardType[]; -static char *saphir_rev = "$Revision: 1.5 $"; +static char *saphir_rev = "$Revision: 1.7 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/sedlbauer.c linux/drivers/isdn/hisax/sedlbauer.c --- v2.4.0-test5/linux/drivers/isdn/hisax/sedlbauer.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/isdn/hisax/sedlbauer.c Sun Aug 6 12:43:42 2000 @@ -1,5 +1,5 @@ -/* $Id: sedlbauer.c,v 1.20 2000/01/20 19:47:45 keil Exp $ - +/* $Id: sedlbauer.c,v 1.23 2000/06/26 08:59:14 keil Exp $ + * * sedlbauer.c low level stuff for Sedlbauer cards * includes support for the Sedlbauer speed star (speed star II), * support for the Sedlbauer speed fax+, @@ -16,71 +16,7 @@ * Sedlbauer AG for informations * Edgar Toernig * - * $Log: sedlbauer.c,v $ - * Revision 1.20 2000/01/20 19:47:45 keil - * Add Fax Class 1 support - * - * Revision 1.19 1999/12/19 13:09:42 keil - * changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for - * signal proof delays - * - * Revision 1.18 1999/11/13 21:25:03 keil - * Support for Speedfax+ PCI - * - * Revision 1.17 1999/09/04 06:20:06 keil - * Changes from kernel set_current_state() - * - * Revision 1.16 1999/08/29 18:23:01 niemann - * Fixed typo in errormsg - * - * Revision 1.15 1999/08/25 17:00:00 keil - * Make ISAR V32bis modem running - * Make LL->HL interface open for additional commands - * - * Revision 1.14 1999/08/11 20:59:22 keil - * new PCI codefix - * fix IRQ problem while unload - * - * Revision 1.13 1999/08/10 16:02:08 calle - * struct pci_dev changed in 2.3.13. Made the necessary changes. - * - * Revision 1.12 1999/08/05 20:43:22 keil - * ISAR analog modem support - * - * Revision 1.11 1999/07/12 21:05:27 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 1.10 1999/07/01 08:12:09 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 1.9 1998/11/15 23:55:20 keil - * changes from 2.0 - * - * Revision 1.8 1998/08/13 23:34:51 keil - * starting speedfax+ (ISAR) support - * - * Revision 1.7 1998/04/15 16:44:33 keil - * new init code - * - * Revision 1.6 1998/02/09 18:46:06 keil - * Support for Sedlbauer PCMCIA (Marcus Niemann) - * - * Revision 1.5 1998/02/02 13:29:45 keil - * fast io - * - * Revision 1.4 1997/11/08 21:35:52 keil - * new l1 init - * - * Revision 1.3 1997/11/06 17:09:28 keil - * New 2.1 init code - * - * Revision 1.2 1997/10/29 18:55:52 keil - * changes for 2.1.60 (irq2dev_map) - * - * Revision 1.1 1997/09/11 17:32:04 keil - * new - * + * This file is (c) under GNU PUBLIC LICENSE * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/sportster.c linux/drivers/isdn/hisax/sportster.c --- v2.4.0-test5/linux/drivers/isdn/hisax/sportster.c Wed Feb 16 17:03:52 2000 +++ linux/drivers/isdn/hisax/sportster.c Sun Aug 6 12:43:42 2000 @@ -1,49 +1,12 @@ -/* $Id: sportster.c,v 1.12 1999/12/23 15:09:32 keil Exp $ - +/* $Id: sportster.c,v 1.13 2000/06/26 08:59:14 keil Exp $ + * * sportster.c low level stuff for USR Sportster internal TA * * Author Karsten Keil (keil@isdn4linux.de) * * Thanks to Christian "naddy" Weisgerber (3Com, US Robotics) for documentation * - * $Log: sportster.c,v $ - * Revision 1.12 1999/12/23 15:09:32 keil - * change email - * - * Revision 1.11 1999/12/19 13:09:42 keil - * changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for - * signal proof delays - * - * Revision 1.10 1999/09/04 06:20:06 keil - * Changes from kernel set_current_state() - * - * Revision 1.9 1999/07/12 21:05:29 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 1.8 1999/07/01 08:12:10 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 1.7 1998/11/15 23:55:22 keil - * changes from 2.0 - * - * Revision 1.6 1998/04/15 16:44:35 keil - * new init code - * - * Revision 1.5 1998/02/02 13:29:46 keil - * fast io - * - * Revision 1.4 1997/11/08 21:35:52 keil - * new l1 init - * - * Revision 1.3 1997/11/06 17:09:29 keil - * New 2.1 init code - * - * Revision 1.2 1997/10/29 18:51:18 keil - * New files - * - * Revision 1.1.2.1 1997/10/17 22:10:58 keil - * new files on 2.0 + * This file is (c) under GNU PUBLIC LICENSE * */ #define __NO_VERSION__ @@ -53,7 +16,7 @@ #include "isdnl1.h" extern const char *CardType[]; -const char *sportster_revision = "$Revision: 1.12 $"; +const char *sportster_revision = "$Revision: 1.13 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/tei.c linux/drivers/isdn/hisax/tei.c --- v2.4.0-test5/linux/drivers/isdn/hisax/tei.c Thu Nov 11 20:11:38 1999 +++ linux/drivers/isdn/hisax/tei.c Sun Aug 6 12:43:42 2000 @@ -1,5 +1,5 @@ -/* $Id: tei.c,v 2.13 1999/07/21 14:46:28 keil Exp $ - +/* $Id: tei.c,v 2.15 2000/06/26 08:59:14 keil Exp $ + * * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden * @@ -10,75 +10,13 @@ * Thanks to Jan den Ouden * Fritz Elfert * - * $Log: tei.c,v $ - * Revision 2.13 1999/07/21 14:46:28 keil - * changes from EICON certification - * - * Revision 2.12 1999/07/01 08:12:11 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 2.11 1998/11/15 23:55:24 keil - * changes from 2.0 - * - * Revision 2.10 1998/05/25 14:08:10 keil - * HiSax 3.0 - * fixed X.75 and leased line to work again - * Point2Point and fixed TEI are runtime options now: - * hisaxctrl 7 1 set PTP - * hisaxctrl 8 - * set fixed TEI to TEIVALUE (0-63) - * - * Revision 2.9 1998/05/25 12:58:23 keil - * HiSax golden code from certification, Don't use !!! - * No leased lines, no X75, but many changes. - * - * Revision 2.8 1998/03/07 22:57:07 tsbogend - * made HiSax working on Linux/Alpha - * - * Revision 2.7 1998/02/12 23:08:11 keil - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 2.6 1998/02/02 13:41:42 keil - * fix MDL_ASSIGN for PtP - * - * Revision 2.5 1997/11/06 17:09:12 keil - * New 2.1 init code - * - * Revision 2.4 1997/10/29 19:04:46 keil - * changes for 2.1 - * - * Revision 2.3 1997/10/01 09:21:43 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 2.2 1997/07/31 19:24:39 keil - * fixed a warning - * - * Revision 2.1 1997/07/31 11:50:16 keil - * ONE TEI and FIXED TEI handling - * - * Revision 2.0 1997/07/27 21:13:30 keil - * New TEI managment - * - * Revision 1.9 1997/06/26 11:18:02 keil - * New managment - * - * Revision 1.8 1997/04/07 22:59:08 keil - * GFP_KERNEL --> GFP_ATOMIC - * - * Revision 1.7 1997/04/06 22:54:03 keil - * Using SKB's - * - * Old log removed/ KKe - * */ #define __NO_VERSION__ #include "hisax.h" #include "isdnl2.h" #include -const char *tei_revision = "$Revision: 2.13 $"; +const char *tei_revision = "$Revision: 2.15 $"; #define ID_REQUEST 1 #define ID_ASSIGNED 2 diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/teleint.c linux/drivers/isdn/hisax/teleint.c --- v2.4.0-test5/linux/drivers/isdn/hisax/teleint.c Wed Feb 16 17:03:52 2000 +++ linux/drivers/isdn/hisax/teleint.c Sun Aug 6 12:43:42 2000 @@ -1,49 +1,10 @@ -/* $Id: teleint.c,v 1.12 1999/12/19 13:09:42 keil Exp $ - +/* $Id: teleint.c,v 1.13 2000/06/26 08:59:14 keil Exp $ + * * teleint.c low level stuff for TeleInt isdn cards * * Author Karsten Keil (keil@isdn4linux.de) * - * - * $Log: teleint.c,v $ - * Revision 1.12 1999/12/19 13:09:42 keil - * changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for - * signal proof delays - * - * Revision 1.11 1999/09/04 06:20:06 keil - * Changes from kernel set_current_state() - * - * Revision 1.10 1999/08/31 11:20:27 paul - * various spelling corrections (new checksums may be needed, Karsten!) - * - * Revision 1.9 1999/07/12 21:05:30 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 1.8 1999/07/01 08:12:12 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 1.7 1998/11/15 23:55:26 keil - * changes from 2.0 - * - * Revision 1.6 1998/04/15 16:45:31 keil - * new init code - * - * Revision 1.5 1998/02/02 13:40:47 keil - * fast io - * - * Revision 1.4 1997/11/08 21:35:53 keil - * new l1 init - * - * Revision 1.3 1997/11/06 17:09:30 keil - * New 2.1 init code - * - * Revision 1.2 1997/10/29 18:55:53 keil - * changes for 2.1.60 (irq2dev_map) - * - * Revision 1.1 1997/09/11 17:32:32 keil - * new - * + * This file is (c) under GNU PUBLIC LICENSE * */ @@ -55,7 +16,7 @@ extern const char *CardType[]; -const char *TeleInt_revision = "$Revision: 1.12 $"; +const char *TeleInt_revision = "$Revision: 1.13 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/teles0.c linux/drivers/isdn/hisax/teles0.c --- v2.4.0-test5/linux/drivers/isdn/hisax/teles0.c Wed Feb 16 17:03:52 2000 +++ linux/drivers/isdn/hisax/teles0.c Sun Aug 6 12:43:42 2000 @@ -1,5 +1,5 @@ -/* $Id: teles0.c,v 2.11 1999/12/23 15:09:32 keil Exp $ - +/* $Id: teles0.c,v 2.12 2000/06/26 08:59:14 keil Exp $ + * * teles0.c low level stuff for Teles Memory IO isdn cards * based on the teles driver from Jan den Ouden * @@ -9,51 +9,7 @@ * Fritz Elfert * Beat Doebeli * - * $Log: teles0.c,v $ - * Revision 2.11 1999/12/23 15:09:32 keil - * change email - * - * Revision 2.10 1999/11/14 23:37:03 keil - * new ISA memory mapped IO - * - * Revision 2.9 1999/07/12 21:05:31 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 2.8 1998/04/15 16:44:28 keil - * new init code - * - * Revision 2.7 1998/03/07 22:57:08 tsbogend - * made HiSax working on Linux/Alpha - * - * Revision 2.6 1998/02/03 23:27:47 keil - * IRQ 9 - * - * Revision 2.5 1998/02/02 13:29:47 keil - * fast io - * - * Revision 2.4 1997/11/08 21:35:54 keil - * new l1 init - * - * Revision 2.3 1997/11/06 17:09:31 keil - * New 2.1 init code - * - * Revision 2.2 1997/10/29 18:55:57 keil - * changes for 2.1.60 (irq2dev_map) - * - * Revision 2.1 1997/07/27 21:47:10 keil - * new interface structures - * - * Revision 2.0 1997/06/26 11:02:43 keil - * New Layer and card interface - * - * Revision 1.8 1997/04/13 19:54:04 keil - * Change in IRQ check delay for SMP - * - * Revision 1.7 1997/04/06 22:54:04 keil - * Using SKB's - * - * removed old log info /KKe + * This file is (c) under GNU PUBLIC LICENSE * */ #define __NO_VERSION__ @@ -64,7 +20,7 @@ extern const char *CardType[]; -const char *teles0_revision = "$Revision: 2.11 $"; +const char *teles0_revision = "$Revision: 2.12 $"; #define TELES_IOMEM_SIZE 0x400 #define byteout(addr,val) outb(val,addr) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/teles3.c linux/drivers/isdn/hisax/teles3.c --- v2.4.0-test5/linux/drivers/isdn/hisax/teles3.c Wed Feb 16 17:03:52 2000 +++ linux/drivers/isdn/hisax/teles3.c Sun Aug 6 12:43:42 2000 @@ -1,5 +1,5 @@ -/* $Id: teles3.c,v 2.15 2000/02/03 16:40:10 keil Exp $ - +/* $Id: teles3.c,v 2.16 2000/06/26 08:59:15 keil Exp $ + * * teles3.c low level stuff for Teles 16.3 & PNP isdn cards * * based on the teles driver from Jan den Ouden @@ -10,81 +10,7 @@ * Fritz Elfert * Beat Doebeli * - * $Log: teles3.c,v $ - * Revision 2.15 2000/02/03 16:40:10 keil - * Fix teles pcmcia - * - * Revision 2.14 1999/12/23 15:09:32 keil - * change email - * - * Revision 2.13 1999/08/30 12:01:28 keil - * HW version v1.3 support - * - * Revision 2.12 1999/07/12 21:05:32 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 2.11 1999/07/01 08:12:14 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 2.10 1999/02/15 14:37:15 cpetig - * oops, missed something in last commit - * - * Revision 2.9 1999/02/15 14:11:02 cpetig - * fixed a bug with Teles PCMCIA, it doesn't have a config register - * - * Revision 2.8 1998/04/15 16:44:30 keil - * new init code - * - * Revision 2.7 1998/02/02 13:29:48 keil - * fast io - * - * Revision 2.6 1997/11/13 16:22:44 keil - * COMPAQ_ISA reset - * - * Revision 2.5 1997/11/12 15:01:25 keil - * COMPAQ_ISA changes - * - * Revision 2.4 1997/11/08 21:35:56 keil - * new l1 init - * - * Revision 2.3 1997/11/06 17:09:33 keil - * New 2.1 init code - * - * Revision 2.2 1997/10/29 18:55:59 keil - * changes for 2.1.60 (irq2dev_map) - * - * Revision 2.1 1997/07/27 21:47:12 keil - * new interface structures - * - * Revision 2.0 1997/06/26 11:02:46 keil - * New Layer and card interface - * - * Revision 1.11 1997/04/13 19:54:05 keil - * Change in IRQ check delay for SMP - * - * Revision 1.10 1997/04/06 22:54:05 keil - * Using SKB's - * - * Revision 1.9 1997/03/22 02:01:07 fritz - * -Reworked toplevel Makefile. From now on, no different Makefiles - * for standalone- and in-kernel-compilation are needed any more. - * -Added local Rules.make for above reason. - * -Experimental changes in teles3.c for enhanced IRQ-checking with - * 2.1.X and SMP kernels. - * -Removed diffstd-script, same functionality is in stddiff -r. - * -Enhanced scripts std2kern and stddiff. - * - * Revision 1.8 1997/02/23 18:43:55 fritz - * Added support for Teles-Vision. - * - * Revision 1.7 1997/01/28 22:48:33 keil - * fixes for Teles PCMCIA (Christof Petig) - * - * Revision 1.6 1997/01/27 15:52:55 keil - * SMP proof,cosmetics, PCMCIA added - * - * removed old log info /KKe + * This file is (c) under GNU PUBLIC LICENSE * */ #define __NO_VERSION__ @@ -94,7 +20,7 @@ #include "isdnl1.h" extern const char *CardType[]; -const char *teles3_revision = "$Revision: 2.15 $"; +const char *teles3_revision = "$Revision: 2.16 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/telespci.c linux/drivers/isdn/hisax/telespci.c --- v2.4.0-test5/linux/drivers/isdn/hisax/telespci.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/isdn/hisax/telespci.c Sun Aug 6 12:43:42 2000 @@ -1,44 +1,11 @@ -/* $Id: telespci.c,v 2.11 1999/12/23 15:09:32 keil Exp $ - +/* $Id: telespci.c,v 2.13 2000/06/26 08:59:15 keil Exp $ + * * telespci.c low level stuff for Teles PCI isdn cards * * Author Ton van Rosmalen * Karsten Keil (keil@isdn4linux.de) * - * - * $Log: telespci.c,v $ - * Revision 2.11 1999/12/23 15:09:32 keil - * change email - * - * Revision 2.10 1999/11/15 14:20:05 keil - * 64Bit compatibility - * - * Revision 2.9 1999/08/11 21:01:34 keil - * new PCI codefix - * - * Revision 2.8 1999/08/10 16:02:10 calle - * struct pci_dev changed in 2.3.13. Made the necessary changes. - * - * Revision 2.7 1999/07/12 21:05:34 keil - * fix race in IRQ handling - * added watchdog for lost IRQs - * - * Revision 2.6 1999/07/01 08:12:15 keil - * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel - * - * Revision 2.5 1998/11/15 23:55:28 keil - * changes from 2.0 - * - * Revision 2.4 1998/10/05 09:38:08 keil - * Fix register addressing - * - * Revision 2.3 1998/05/25 12:58:26 keil - * HiSax golden code from certification, Don't use !!! - * No leased lines, no X75, but many changes. - * - * Revision 2.1 1998/04/15 16:38:23 keil - * Add S0Box and Teles PCI support - * + * This file is (c) under GNU PUBLIC LICENSE * */ #define __NO_VERSION__ @@ -50,7 +17,7 @@ #include extern const char *CardType[]; -const char *telespci_revision = "$Revision: 2.11 $"; +const char *telespci_revision = "$Revision: 2.13 $"; #define ZORAN_PO_RQ_PEN 0x02000000 #define ZORAN_PO_WR 0x00800000 diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/w6692.c linux/drivers/isdn/hisax/w6692.c --- v2.4.0-test5/linux/drivers/isdn/hisax/w6692.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/isdn/hisax/w6692.c Sun Aug 6 12:43:42 2000 @@ -1,28 +1,11 @@ -/* $Id: w6692.c,v 1.4 2000/03/16 23:24:11 werner Exp $ - +/* $Id: w6692.c,v 1.7 2000/06/26 08:59:15 keil Exp $ + * * w6692.c Winbond W6692 specific routines * * Author Petr Novak * (based on HiSax driver by Karsten Keil) * * This file is (c) under GNU PUBLIC LICENSE - * - * $Log: w6692.c,v $ - * Revision 1.4 2000/03/16 23:24:11 werner - * - * Fixed an additional location - * - * Revision 1.3 2000/03/16 22:41:36 werner - * - * Tried to fix second B-channel problem (still not tested) - * - * Revision 1.2 2000/02/26 00:35:13 keil - * Fix skb freeing in interrupt context - * - * Revision 1.1 1999/09/04 06:28:58 keil - * first revision - * - * * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/hisax/w6692.h linux/drivers/isdn/hisax/w6692.h --- v2.4.0-test5/linux/drivers/isdn/hisax/w6692.h Thu Nov 11 20:11:38 1999 +++ linux/drivers/isdn/hisax/w6692.h Sun Aug 6 12:43:42 2000 @@ -1,18 +1,10 @@ -/* $Id: w6692.h,v 1.1 1999/09/04 06:28:58 keil Exp $ - +/* $Id: w6692.h,v 1.2 2000/06/26 08:59:15 keil Exp $ + * * w6692.h Winbond W6692 specific defines * * Author Petr Novak * - * - * $Log: w6692.h,v $ - * Revision 1.1 1999/09/04 06:28:58 keil - * first revision - * - * - * Revision 1.0 1999/08/28 21:58:00 pnovak - * first version - * + * This file is (c) under GNU PUBLIC LICENSE * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/isdn_audio.c linux/drivers/isdn/isdn_audio.c --- v2.4.0-test5/linux/drivers/isdn/isdn_audio.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/isdn/isdn_audio.c Sun Aug 6 12:43:42 2000 @@ -1,4 +1,4 @@ -/* $Id: isdn_audio.c,v 1.17 1999/08/17 11:10:52 paul Exp $ +/* $Id: isdn_audio.c,v 1.21 2000/06/20 18:01:55 keil Exp $ * Linux ISDN subsystem, audio conversion and compression (linklevel). * @@ -20,73 +20,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Log: isdn_audio.c,v $ - * Revision 1.17 1999/08/17 11:10:52 paul - * don't try to use x86 assembler on non-x86! - * - * Revision 1.16 1999/08/06 12:47:35 calle - * Using __GNUC__ == 2 && __GNUC_MINOR__ < 95 how to define - * ISDN_AUDIO_OPTIMIZE_ON_X386_WITH_ASM_IF_GCC_ALLOW_IT - * - * Revision 1.15 1999/08/06 12:02:52 calle - * egcs 2.95 complain about invalid asm statement: - * "fixed or forbidden register 2 (cx) was spilled for class CREG." - * Using ISDN_AUDIO_OPTIMIZE_ON_X386_WITH_ASM_IF_GCC_ALLOW_IT and not - * define it at the moment. - * - * Revision 1.14 1999/07/11 17:14:06 armin - * Added new layer 2 and 3 protocols for Fax and DSP functions. - * Moved "Add CPN to RING message" to new register S23, - * "Display message" is now correct on register S13 bit 7. - * New audio command AT+VDD implemented (deactivate DTMF decoder and - * activate possible existing hardware/DSP decoder). - * Moved some tty defines to .h file. - * Made whitespace possible in AT command line. - * Some AT-emulator output bugfixes. - * First Fax G3 implementations. - * - * Revision 1.13 1999/04/12 12:33:09 fritz - * Changes from 2.0 tree. - * - * Revision 1.12 1998/07/26 18:48:43 armin - * Added silence detection in voice receive mode. - * - * Revision 1.11 1998/04/10 10:35:10 paul - * fixed (silly?) warnings from egcs on Alpha. - * - * Revision 1.10 1998/02/20 17:09:40 fritz - * Changes for recent kernels. - * - * Revision 1.9 1997/10/01 09:20:25 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.8 1997/03/02 14:29:16 fritz - * More ttyI related cleanup. - * - * Revision 1.7 1997/02/03 22:44:11 fritz - * Reformatted according CodingStyle - * - * Revision 1.6 1996/06/06 14:43:31 fritz - * Changed to support DTMF decoding on audio playback also. - * - * Revision 1.5 1996/06/05 02:24:08 fritz - * Added DTMF decoder for audio mode. - * - * Revision 1.4 1996/05/17 03:48:01 fritz - * Removed some test statements. - * Added revision string. - * - * Revision 1.3 1996/05/10 08:48:11 fritz - * Corrected adpcm bugs. - * - * Revision 1.2 1996/04/30 09:31:17 fritz - * General rewrite. - * - * Revision 1.1.1.1 1996/04/28 12:25:40 fritz - * Taken under CVS control - * */ #define __NO_VERSION__ @@ -95,7 +28,7 @@ #include "isdn_audio.h" #include "isdn_common.h" -char *isdn_audio_revision = "$Revision: 1.17 $"; +char *isdn_audio_revision = "$Revision: 1.21 $"; /* * Misc. lookup-tables. @@ -250,9 +183,9 @@ }; #define NCOEFF 16 /* number of frequencies to be analyzed */ -#define DTMF_TRESH 50000 /* above this is dtmf */ -#define SILENCE_TRESH 100 /* below this is silence */ -#define H2_TRESH 10000 /* 2nd harmonic */ +#define DTMF_TRESH 25000 /* above this is dtmf */ +#define SILENCE_TRESH 200 /* below this is silence */ +#define H2_TRESH 20000 /* 2nd harmonic */ #define AMP_BITS 9 /* bits per sample, reduced to avoid overflow */ #define LOGRP 0 #define HIGRP 1 @@ -293,7 +226,7 @@ }; static inline void -isdn_audio_tlookup(const void *table, void *buff, unsigned long n) +isdn_audio_tlookup(const u_char *table, u_char *buff, unsigned long n) { #ifdef __i386__ unsigned long d0, d1, d2, d3; @@ -307,10 +240,8 @@ : "0"((long) table), "1"(n), "2"((long) buff), "3"((long) buff) : "memory", "ax"); #else - unsigned char* b = (unsigned char*) buff; - unsigned char* t = (unsigned char*) table; while (n--) - *b++ = t[*b]; + *buff++ = table[*(unsigned char *)buff]; #endif } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/isdn_audio.h linux/drivers/isdn/isdn_audio.h --- v2.4.0-test5/linux/drivers/isdn/isdn_audio.h Thu Aug 12 09:42:33 1999 +++ linux/drivers/isdn/isdn_audio.h Sun Aug 6 12:43:42 2000 @@ -1,4 +1,4 @@ -/* $Id: isdn_audio.h,v 1.8 1999/07/11 17:14:07 armin Exp $ +/* $Id: isdn_audio.h,v 1.9 2000/05/11 22:29:20 kai Exp $ * Linux ISDN subsystem, audio conversion and compression (linklevel). * @@ -17,39 +17,6 @@ * 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. - * - * $Log: isdn_audio.h,v $ - * Revision 1.8 1999/07/11 17:14:07 armin - * Added new layer 2 and 3 protocols for Fax and DSP functions. - * Moved "Add CPN to RING message" to new register S23, - * "Display message" is now correct on register S13 bit 7. - * New audio command AT+VDD implemented (deactivate DTMF decoder and - * activate possible existing hardware/DSP decoder). - * Moved some tty defines to .h file. - * Made whitespace possible in AT command line. - * Some AT-emulator output bugfixes. - * First Fax G3 implementations. - * - * Revision 1.7 1999/04/12 12:33:11 fritz - * Changes from 2.0 tree. - * - * Revision 1.6 1998/07/26 18:48:44 armin - * Added silence detection in voice receive mode. - * - * Revision 1.5 1997/02/03 22:45:21 fritz - * Reformatted according CodingStyle - * - * Revision 1.4 1996/06/06 14:43:32 fritz - * Changed to support DTMF decoding on audio playback also. - * - * Revision 1.3 1996/06/05 02:24:09 fritz - * Added DTMF decoder for audio mode. - * - * Revision 1.2 1996/05/10 08:48:32 fritz - * Corrected adpcm bugs. - * - * Revision 1.1 1996/04/30 09:29:06 fritz - * Taken under CVS control. * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/isdn_cards.c linux/drivers/isdn/isdn_cards.c --- v2.4.0-test5/linux/drivers/isdn/isdn_cards.c Mon Jul 10 16:47:23 2000 +++ linux/drivers/isdn/isdn_cards.c Sun Aug 6 12:43:42 2000 @@ -1,4 +1,4 @@ -/* $Id: isdn_cards.c,v 1.10 1999/07/20 06:41:28 calle Exp $ +/* $Id: isdn_cards.c,v 1.11 2000/05/11 22:29:20 kai Exp $ * Linux ISDN subsystem, initialization for non-modularized drivers. * @@ -18,38 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Log: isdn_cards.c,v $ - * Revision 1.10 1999/07/20 06:41:28 calle - * Bugfix: After the redesign of the AVM B1 driver, the driver didn't even - * compile, if not selected as modules. - * - * Revision 1.9 1999/04/12 12:33:11 fritz - * Changes from 2.0 tree. - * - * Revision 1.8 1999/03/29 11:13:23 armin - * Added eicon driver init. - * - * Revision 1.7 1998/02/20 17:24:28 fritz - * Added ACT2000 init. - * - * Revision 1.6 1997/04/23 18:56:03 fritz - * Old Teles driver removed, Changed doc and scripts accordingly. - * - * Revision 1.5 1997/03/30 17:10:36 calle - * added support for AVM-B1-PCI card. - * - * Revision 1.4 1997/03/04 21:59:44 calle - * Added AVM-B1-CAPI2.0 driver - * - * Revision 1.3 1997/02/03 23:31:14 fritz - * Reformatted according CodingStyle - * - * Revision 1.2 1996/10/13 19:52:17 keil - * HiSax support - * - * Revision 1.1 1996/04/20 16:04:36 fritz - * Initial revision - * */ #include @@ -75,9 +43,6 @@ extern void capi_init(void); extern void capidrv_init(void); #endif - -extern int act2000_init(void); - void isdn_cards_init(void) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/isdn_cards.h linux/drivers/isdn/isdn_cards.h --- v2.4.0-test5/linux/drivers/isdn/isdn_cards.h Sun May 23 10:03:42 1999 +++ linux/drivers/isdn/isdn_cards.h Sun Aug 6 12:43:42 2000 @@ -1,4 +1,4 @@ -/* $Id: isdn_cards.h,v 1.3 1999/04/12 12:33:13 fritz Exp $ +/* $Id: isdn_cards.h,v 1.4 2000/05/11 22:29:20 kai Exp $ * Linux ISDN subsystem, initialization for non-modularized drivers. * @@ -17,16 +17,6 @@ * 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. - * - * $Log: isdn_cards.h,v $ - * Revision 1.3 1999/04/12 12:33:13 fritz - * Changes from 2.0 tree. - * - * Revision 1.2 1997/02/03 23:31:55 fritz - * Reformatted according CodingStyle - * - * Revision 1.1 1996/04/20 16:04:03 fritz - * Initial revision * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c --- v2.4.0-test5/linux/drivers/isdn/isdn_common.c Fri Jul 14 12:12:10 2000 +++ linux/drivers/isdn/isdn_common.c Tue Aug 8 15:03:57 2000 @@ -1,4 +1,4 @@ -/* $Id: isdn_common.c,v 1.101 2000/04/07 14:50:34 calle Exp $ +/* $Id: isdn_common.c,v 1.108 2000/06/24 15:52:47 keil Exp $ * Linux ISDN subsystem, common used functions (linklevel). * @@ -20,417 +20,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Log: isdn_common.c,v $ - * Revision 1.101 2000/04/07 14:50:34 calle - * Bugfix: on my system 2.3.99-pre3 Dual PII 350, unload of module isdn.o - * hangs if vfree is called with interrupt disabled. After moving - * restore_flags in front of vfree it doesn't hang. - * - * Revision 1.100 2000/03/03 16:37:11 kai - * incorporated some cosmetic changes from the official kernel tree back - * into CVS - * - * Revision 1.99 2000/02/26 01:00:52 keil - * changes from 2.3.47 - * - * Revision 1.98 2000/02/16 14:56:27 paul - * translated ISDN_MODEM_ANZREG to ISDN_MODEM_NUMREG for english speakers - * - * Revision 1.97 2000/01/23 18:45:37 keil - * Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN) - * - * Revision 1.96 2000/01/20 19:55:33 keil - * Add FAX Class 1 support - * - * Revision 1.95 2000/01/09 20:43:13 detabc - * exand logical bind-group's for both call's (in and out). - * add first part of kernel-config-help for abc-extension. - * - * Revision 1.94 1999/11/20 22:14:13 detabc - * added channel dial-skip in case of external use - * (isdn phone or another isdn device) on the same NTBA. - * usefull with two or more card's connected the different NTBA's. - * global switchable in kernel-config and also per netinterface. - * - * add auto disable of netinterface's in case of: - * to many connection's in short time. - * config mistakes (wrong encapsulation, B2-protokoll or so on) on local - * or remote side. - * wrong password's or something else to a ISP (syncppp). - * - * possible encapsulations for this future are: - * ISDN_NET_ENCAP_SYNCPPP, ISDN_NET_ENCAP_UIHDLC, ISDN_NET_ENCAP_RAWIP, - * and ISDN_NET_ENCAP_CISCOHDLCK. - * - * Revision 1.93 1999/11/04 13:11:36 keil - * Reinit of v110 structs - * - * Revision 1.92 1999/10/31 15:59:50 he - * more skb headroom checks - * - * Revision 1.91 1999/10/28 22:48:45 armin - * Bugfix: isdn_free_channel() now frees the channel, - * even when the usage of the ttyI has changed. - * - * Revision 1.90 1999/10/27 21:21:17 detabc - * Added support for building logically-bind-group's per interface. - * usefull for outgoing call's with more then one isdn-card. - * - * Switchable support to dont reset the hangup-timeout for - * receive frames. Most part's of the timru-rules for receiving frames - * are now obsolete. If the input- or forwarding-firewall deny - * the frame, the line will be not hold open. - * - * Revision 1.89 1999/10/16 14:46:47 keil - * replace kmalloc with vmalloc for the big dev struct - * - * Revision 1.88 1999/10/02 00:39:26 he - * Fixed a 2.3.x wait queue initialization (was causing panics) - * - * Revision 1.87 1999/09/12 16:19:39 detabc - * added abc features - * low cost routing for net-interfaces (only the HL side). - * need more implementation in the isdnlog-utility - * udp info support (first part). - * different EAZ on outgoing call's. - * more checks on D-Channel callbacks (double use of channels). - * tested and running with kernel 2.3.17 - * - * Revision 1.86 1999/07/31 12:59:42 armin - * Added tty fax capabilities. - * - * Revision 1.85 1999/07/29 16:58:35 armin - * Bugfix: DLE handling in isdn_readbchan() - * - * Revision 1.84 1999/07/25 16:21:10 keil - * fix number matching - * - * Revision 1.83 1999/07/13 21:02:05 werner - * Added limit possibilty of driver b_channel resources (ISDN_STAT_DISCH) - * - * Revision 1.82 1999/07/12 21:06:50 werner - * Fixed problem when loading more than one driver temporary - * - * Revision 1.81 1999/07/11 17:14:09 armin - * Added new layer 2 and 3 protocols for Fax and DSP functions. - * Moved "Add CPN to RING message" to new register S23, - * "Display message" is now correct on register S13 bit 7. - * New audio command AT+VDD implemented (deactivate DTMF decoder and - * activate possible existing hardware/DSP decoder). - * Moved some tty defines to .h file. - * Made whitespace possible in AT command line. - * Some AT-emulator output bugfixes. - * First Fax G3 implementations. - * - * Revision 1.80 1999/07/07 10:14:00 detabc - * remove unused messages - * - * Revision 1.79 1999/07/05 23:51:30 werner - * Allow limiting of available HiSax B-chans per card. Controlled by hisaxctrl - * hisaxctrl id 10 - * - * Revision 1.78 1999/07/05 20:21:15 werner - * changes to use diversion sources for all kernel versions. - * removed static device, only proc filesystem used - * - * Revision 1.77 1999/07/01 08:29:50 keil - * compatibility to 2.3 kernel - * - * Revision 1.76 1999/06/29 16:16:44 calle - * Let ISDN_CMD_UNLOAD work with open isdn devices without crash again. - * Also right unlocking (ISDN_CMD_UNLOCK) is done now. - * isdnlog should check returncode of read(2) calls. - * - * Revision 1.75 1999/04/18 14:06:47 fritz - * Removed TIMRU stuff. - * - * Revision 1.74 1999/04/12 13:16:45 fritz - * Changes from 2.0 tree. - * - * Revision 1.73 1999/04/12 12:33:15 fritz - * Changes from 2.0 tree. - * - * Revision 1.72 1999/03/02 12:04:44 armin - * -added ISDN_STAT_ADDCH to increase supported channels after - * register_isdn(). - * -ttyI now goes on-hook on ATZ when B-Ch is connected. - * -added timer-function for register S7 (Wait for Carrier). - * -analog modem (ISDN_PROTO_L2_MODEM) implementations. - * -on L2_MODEM a string will be appended to the CONNECT-Message, - * which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN. - * -variable "dialing" used for ATA also, for interrupting call - * establishment and register S7. - * - * Revision 1.71 1999/01/28 09:10:43 armin - * Fixed bad while-loop in isdn_readbch(). - * - * Revision 1.70 1999/01/15 19:58:54 he - * removed compatibiltity macro - * - * Revision 1.69 1998/09/07 21:59:58 he - * flush method for 2.1.118 and above - * updated IIOCTLNETGPN - * - * Revision 1.68 1998/08/31 21:09:45 he - * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface' - * peer phone number) - * - * Revision 1.67 1998/06/26 15:12:21 fritz - * Added handling of STAT_ICALL with incomplete CPN. - * Added AT&L for ttyI emulator. - * Added more locking stuff in tty_write. - * - * Revision 1.66 1998/06/17 19:50:41 he - * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay()) - * brute force fix to avoid Ugh's in isdn_tty_write() - * cleaned up some dead code - * - * - * Revision 1.62 1998/04/14 16:28:43 he - * Fixed user space access with interrupts off and remaining - * copy_{to,from}_user() -> -EFAULT return codes - * - * Revision 1.61 1998/03/22 18:50:46 hipp - * Added BSD Compression for syncPPP .. UNTESTED at the moment - * - * Revision 1.60 1998/03/19 13:18:18 keil - * Start of a CAPI like interface for supplementary Service - * first service: SUSPEND - * - * Revision 1.59 1998/03/09 17:46:23 he - * merged in 2.1.89 changes - * - * Revision 1.58 1998/03/07 22:35:24 fritz - * Starting generic module support (Nothing usable yet). - * - * Revision 1.57 1998/03/07 18:21:01 cal - * Dynamic Timeout-Rule-Handling vs. 971110 included - * - * Revision 1.56 1998/02/25 17:49:38 he - * Changed return codes caused be failing copy_{to,from}_user to -EFAULT - * - * Revision 1.55 1998/02/23 23:35:32 fritz - * Eliminated some compiler warnings. - * - * Revision 1.54 1998/02/22 19:44:19 fritz - * Bugfixes and improvements regarding V.110, V.110 now running. - * - * Revision 1.53 1998/02/20 17:18:05 fritz - * Changes for recent kernels. - * Added common stub for sending commands to lowlevel. - * Added V.110. - * - * Revision 1.52 1998/01/31 22:05:57 keil - * Lots of changes for X.25 support: - * Added generic support for connection-controlling encapsulation protocols - * Added support of BHUP status message - * Added support for additional p_encap X25IFACE - * Added support for kernels >= 2.1.72 - * - * Revision 1.51 1998/01/31 19:17:29 calle - * merged changes from and for 2.1.82 - * - * Revision 1.50 1997/12/12 06:12:11 calle - * moved EXPORT_SYMBOL(register_isdn) from isdn_syms.c to isdn_common.c - * - * Revision 1.49 1997/11/06 17:16:52 keil - * Sync to 2.1.62 changes - * - * Revision 1.48 1997/11/02 23:55:50 keil - * Andi Kleen's changes for 2.1.60 - * without it the isdninfo and isdnctrl devices won't work - * - * Revision 1.47 1997/10/09 21:28:46 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * New L1 error status (not yet in use). - * Cleaned up obsolete structures. - * Implemented Cisco-SLARP. - * Changed local net-interface data to be dynamically allocated. - * Removed old 2.0 compatibility stuff. - * - * Revision 1.46 1997/10/01 09:20:27 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.45 1997/08/21 23:11:41 fritz - * Added changes for kernels >= 2.1.45 - * - * Revision 1.44 1997/05/27 15:17:23 fritz - * Added changes for recent 2.1.x kernels: - * changed return type of isdn_close - * queue_task_* -> queue_task - * clear/set_bit -> test_and_... where apropriate. - * changed type of hard_header_cache parameter. - * - * Revision 1.43 1997/03/31 14:09:43 fritz - * Fixed memory leak in isdn_close(). - * - * Revision 1.42 1997/03/30 16:51:08 calle - * changed calls to copy_from_user/copy_to_user and removed verify_area - * were possible. - * - * Revision 1.41 1997/03/24 22:54:41 fritz - * Some small fixes in debug code. - * - * Revision 1.40 1997/03/08 08:13:51 fritz - * Bugfix: IIOCSETMAP (Set mapping) was broken. - * - * Revision 1.39 1997/03/07 01:32:54 fritz - * Added proper ifdef's for CONFIG_ISDN_AUDIO - * - * Revision 1.38 1997/03/05 21:15:02 fritz - * Fix: reduced stack usage of isdn_ioctl() and isdn_set_allcfg() - * - * Revision 1.37 1997/03/02 14:29:18 fritz - * More ttyI related cleanup. - * - * Revision 1.36 1997/02/28 02:32:40 fritz - * Cleanup: Moved some tty related stuff from isdn_common.c - * to isdn_tty.c - * Bugfix: Bisync protocol did not behave like documented. - * - * Revision 1.35 1997/02/21 13:01:19 fritz - * Changes CAUSE message output in kernel log. - * - * Revision 1.34 1997/02/10 20:12:43 fritz - * Changed interface for reporting incoming calls. - * - * Revision 1.33 1997/02/10 10:05:42 fritz - * More changes for Kernel 2.1.X - * Symbol information moved to isdn_syms.c - * - * Revision 1.32 1997/02/03 22:55:26 fritz - * Reformatted according CodingStyle. - * Changed isdn_writebuf_stub static. - * Slow down tty-RING counter. - * skb->free stuff replaced by macro. - * Bugfix in audio-skb locking. - * Bugfix in HL-driver locking. - * - * Revision 1.31 1997/01/17 01:19:18 fritz - * Applied chargeint patch. - * - * Revision 1.30 1997/01/14 01:27:47 fritz - * Changed audio receive not to rely on skb->users and skb->lock. - * Added ATI2 and related variables. - * Started adding full-duplex audio capability. - * - * Revision 1.29 1997/01/12 23:33:03 fritz - * Made isdn_all_eaz foolproof. - * - * Revision 1.28 1996/11/13 02:33:19 fritz - * Fixed a race condition. - * - * Revision 1.27 1996/10/27 22:02:41 keil - * return codes for ISDN_STAT_ICALL - * - * Revision 1.26 1996/10/23 11:59:40 fritz - * More compatibility changes. - * - * Revision 1.25 1996/10/22 23:13:54 fritz - * Changes for compatibility to 2.0.X and 2.1.X kernels. - * - * Revision 1.24 1996/10/11 14:02:03 fritz - * Bugfix: call to isdn_ppp_timer_timeout() never compiled, because of - * typo in #ifdef. - * - * Revision 1.23 1996/06/25 18:35:38 fritz - * Fixed bogus memory access in isdn_set_allcfg(). - * - * Revision 1.22 1996/06/24 17:37:37 fritz - * Bugfix: isdn_timer_ctrl() did restart timer, even if it - * was already running. - * lowlevel driver locking did use wrong parameters. - * - * Revision 1.21 1996/06/15 14:58:20 fritz - * Added version signatures for data structures used - * by userlevel programs. - * - * Revision 1.20 1996/06/12 16:01:49 fritz - * Bugfix: Remote B-channel hangup sometimes did not result - * in a NO CARRIER on tty. - * - * Revision 1.19 1996/06/11 14:52:04 hipp - * minor bugfix in isdn_writebuf_skb_stub() - * - * Revision 1.18 1996/06/06 14:51:51 fritz - * Changed to support DTMF decoding on audio playback also. - * - * Revision 1.17 1996/06/05 02:24:10 fritz - * Added DTMF decoder for audio mode. - * - * Revision 1.16 1996/06/03 20:09:05 fritz - * Bugfix: called wrong function pointer for locking in - * isdn_get_free_channel(). - * - * Revision 1.15 1996/05/31 01:10:54 fritz - * Bugfixes: - * Lowlevel modules did not get locked correctly. - * Did show wrong revision when initializing. - * Minor fixes in ioctl code. - * sk_buff did not get freed, if error in writebuf_stub. - * - * Revision 1.14 1996/05/18 01:36:55 fritz - * Added spelling corrections and some minor changes - * to stay in sync with kernel. - * - * Revision 1.13 1996/05/17 15:43:30 fritz - * Bugfix: decrement of rcvcount in readbchan() corrected. - * - * Revision 1.12 1996/05/17 03:55:43 fritz - * Changed DLE handling for audio receive. - * Some cleanup. - * Added display of isdn_audio_revision. - * - * Revision 1.11 1996/05/11 21:51:32 fritz - * Changed queue management to use sk_buffs. - * - * Revision 1.10 1996/05/10 08:49:16 fritz - * Checkin before major changes of tty-code. - * - * Revision 1.9 1996/05/07 09:19:41 fritz - * Adapted to changes in isdn_tty.c - * - * Revision 1.8 1996/05/06 11:34:51 hipp - * fixed a few bugs - * - * Revision 1.7 1996/05/02 03:55:17 fritz - * Bugfixes: - * - B-channel connect message for modem devices - * sometimes did not result in a CONNECT-message. - * - register_isdn did not check for driverId-conflicts. - * - * Revision 1.6 1996/04/30 20:57:21 fritz - * Commit test - * - * Revision 1.5 1996/04/20 16:19:07 fritz - * Changed slow timer handlers to increase accuracy. - * Added statistic information for usage by xisdnload. - * Fixed behaviour of isdnctrl-device on non-blocked io. - * Fixed all io to go through generic writebuf-function without - * bypassing. Same for incoming data. - * Fixed bug: Last channel had been unusable. - * Fixed kfree of tty xmit_buf on ppp initialization failure. - * - * Revision 1.4 1996/02/11 02:33:26 fritz - * Fixed bug in main timer-dispatcher. - * Bugfix: Lot of tty-callbacks got called regardless of the events already - * been handled by network-devices. - * Changed ioctl-names. - * - * Revision 1.3 1996/01/22 05:16:11 fritz - * Changed ioctl-names. - * Fixed bugs in isdn_open and isdn_close regarding PPP_MINOR. - * - * Revision 1.2 1996/01/21 16:52:40 fritz - * Support for sk_buffs added, changed header-stuffing. - * - * Revision 1.1 1996/01/09 04:12:52 fritz - * Initial revision - * */ #include @@ -459,7 +48,7 @@ isdn_dev *dev = (isdn_dev *) 0; -static char *isdn_revision = "$Revision: 1.101 $"; +static char *isdn_revision = "$Revision: 1.108 $"; extern char *isdn_net_revision; extern char *isdn_tty_revision; @@ -484,6 +73,7 @@ static void set_global_features(void); static void isdn_register_devfs(int); static void isdn_unregister_devfs(int); +static int isdn_wildmat(char *s, char *p); void isdn_lock_drivers(void) @@ -577,7 +167,7 @@ * [^xyz] matches any single character not in the set of characters */ -int +static int isdn_wildmat(char *s, char *p) { register int last; @@ -623,6 +213,23 @@ return (*s == '\0')?0:nostar; } +int isdn_msncmp( const char * msn1, const char * msn2 ) +{ + char TmpMsn1[ ISDN_MSNLEN ]; + char TmpMsn2[ ISDN_MSNLEN ]; + char *p; + + for ( p = TmpMsn1; *msn1 && *msn1 != ':'; ) // Strip off a SPID + *p++ = *msn1++; + *p = '\0'; + + for ( p = TmpMsn2; *msn2 && *msn2 != ':'; ) // Strip off a SPID + *p++ = *msn2++; + *p = '\0'; + + return isdn_wildmat( TmpMsn1, TmpMsn2 ); +} + static void isdn_free_queue(struct sk_buff_head *queue) { @@ -686,10 +293,6 @@ } if (tf & ISDN_TIMER_CARRIER) isdn_tty_carrier_timeout(); -#if (defined CONFIG_ISDN_PPP) && (defined CONFIG_ISDN_MPP) - if (tf & ISDN_TIMER_IPPP) - isdn_ppp_timer_timeout(); -#endif } } if (tf) @@ -850,6 +453,7 @@ int r; int retval = 0; isdn_ctrl cmd; + isdn_net_dev *p; di = c->driver; i = isdn_dc2minor(di, c->arg); @@ -898,7 +502,7 @@ return 0; } /* Try to find a network-interface which will accept incoming call */ - r = ((c->command == ISDN_STAT_ICALLW) ? 0 : isdn_net_find_icall(di, c->arg, i, c->parm.setup)); + r = ((c->command == ISDN_STAT_ICALLW) ? 0 : isdn_net_find_icall(di, c->arg, i, &c->parm.setup)); switch (r) { case 0: /* No network-device replies. @@ -907,7 +511,7 @@ * 3 on eventually match, if CID is longer. */ if (c->command == ISDN_STAT_ICALL) - if ((retval = isdn_tty_find_icall(di, c->arg, c->parm.setup))) return(retval); + if ((retval = isdn_tty_find_icall(di, c->arg, &c->parm.setup))) return(retval); #ifdef CONFIG_ISDN_DIVERSION if (divert_if) if ((retval = divert_if->stat_callback(c))) @@ -928,9 +532,16 @@ cmd.driver = di; cmd.arg = c->arg; cmd.command = ISDN_CMD_ACCEPTD; - isdn_command(&cmd); - retval = 1; + for ( p = dev->netdev; p; p = p->next ) + if ( p->local->isdn_channel == cmd.arg ) + { + strcpy( cmd.parm.setup.eazmsn, p->local->msn ); + isdn_command(&cmd); + retval = 1; + break; + } break; + case 2: /* For calling back, first reject incoming call ... */ case 3: /* Interface found, but down, reject call actively */ retval = 2; @@ -1379,54 +990,78 @@ ulong flags; int drvidx; int chidx; + int retval; char *p; if (off != &file->f_pos) return -ESPIPE; + lock_kernel(); if (minor == ISDN_MINOR_STATUS) { if (!file->private_data) { - if (file->f_flags & O_NONBLOCK) - return -EAGAIN; + if (file->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + goto out; + } interruptible_sleep_on(&(dev->info_waitq)); } p = isdn_statstr(); file->private_data = 0; if ((len = strlen(p)) <= count) { - if (copy_to_user(buf, p, len)) - return -EFAULT; + if (copy_to_user(buf, p, len)) { + retval = -EFAULT; + goto out; + } *off += len; - return len; + retval = len; + goto out; } - return 0; + retval = 0; + goto out; + } + if (!dev->drivers) { + retval = -ENODEV; + goto out; } - if (!dev->drivers) - return -ENODEV; if (minor < ISDN_MINOR_CTRL) { + printk(KERN_WARNING "isdn_read minor %d obsolete!\n", minor); drvidx = isdn_minor2drv(minor); - if (drvidx < 0) - return -ENODEV; - if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) - return -ENODEV; + if (drvidx < 0) { + retval = -ENODEV; + goto out; + } + if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) { + retval = -ENODEV; + goto out; + } chidx = isdn_minor2chan(minor); - if( ! (p = kmalloc(count,GFP_KERNEL)) ) return -ENOMEM; + if (!(p = kmalloc(count, GFP_KERNEL))) { + retval = -ENOMEM; + goto out; + } save_flags(flags); cli(); len = isdn_readbchan(drvidx, chidx, p, 0, count, &dev->drv[drvidx]->rcv_waitq[chidx]); *off += len; restore_flags(flags); - if( copy_to_user(buf,p,len) ) len = -EFAULT; + if (copy_to_user(buf,p,len)) + len = -EFAULT; kfree(p); - return len; + retval = len; + goto out; } if (minor <= ISDN_MINOR_CTRLMAX) { drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL); - if (drvidx < 0) - return -ENODEV; + if (drvidx < 0) { + retval = -ENODEV; + goto out; + } if (!dev->drv[drvidx]->stavail) { - if (file->f_flags & O_NONBLOCK) - return -EAGAIN; + if (file->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + goto out; + } interruptible_sleep_on(&(dev->drv[drvidx]->st_waitq)); } if (dev->drv[drvidx]->interface->readstat) @@ -1443,17 +1078,23 @@ dev->drv[drvidx]->stavail = 0; restore_flags(flags); *off += len; - return len; + retval = len; + goto out; } #ifdef CONFIG_ISDN_PPP - if (minor <= ISDN_MINOR_PPPMAX) - return (isdn_ppp_read(minor - ISDN_MINOR_PPP, file, buf, count)); + if (minor <= ISDN_MINOR_PPPMAX) { + retval = isdn_ppp_read(minor - ISDN_MINOR_PPP, file, buf, count); + goto out; + } #endif - return -ENODEV; + retval = -ENODEV; + out: + unlock_kernel(); + return retval; } static loff_t -isdn_lseek(struct file *file, loff_t offset, int orig) +isdn_llseek(struct file *file, loff_t offset, int orig) { return -ESPIPE; } @@ -1464,6 +1105,7 @@ uint minor = MINOR(file->f_dentry->d_inode->i_rdev); int drvidx; int chidx; + int retval; if (off != &file->f_pos) return -ESPIPE; @@ -1472,21 +1114,31 @@ return -EPERM; if (!dev->drivers) return -ENODEV; + + lock_kernel(); if (minor < ISDN_MINOR_CTRL) { + printk(KERN_WARNING "isdn_write minor %d obsolete!\n", minor); drvidx = isdn_minor2drv(minor); - if (drvidx < 0) - return -ENODEV; - if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) - return -ENODEV; + if (drvidx < 0) { + retval = -ENODEV; + goto out; + } + if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) { + retval = -ENODEV; + goto out; + } chidx = isdn_minor2chan(minor); while (isdn_writebuf_stub(drvidx, chidx, buf, count, 1) != count) interruptible_sleep_on(&dev->drv[drvidx]->snd_waitq[chidx]); - return count; + retval = count; + goto out; } if (minor <= ISDN_MINOR_CTRLMAX) { drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL); - if (drvidx < 0) - return -ENODEV; + if (drvidx < 0) { + retval = -ENODEV; + goto out; + } /* * We want to use the isdnctrl device to load the firmware * @@ -1494,16 +1146,22 @@ return -ENODEV; */ if (dev->drv[drvidx]->interface->writecmd) - return (dev->drv[drvidx]->interface-> - writecmd(buf, count, 1, drvidx, isdn_minor2chan(minor))); + retval = dev->drv[drvidx]->interface-> + writecmd(buf, count, 1, drvidx, isdn_minor2chan(minor)); else - return count; + retval = count; + goto out; } #ifdef CONFIG_ISDN_PPP - if (minor <= ISDN_MINOR_PPPMAX) - return (isdn_ppp_write(minor - ISDN_MINOR_PPP, file, buf, count)); + if (minor <= ISDN_MINOR_PPPMAX) { + retval = isdn_ppp_write(minor - ISDN_MINOR_PPP, file, buf, count); + goto out; + } #endif - return -ENODEV; + retval = -ENODEV; + out: + unlock_kernel(); + return retval; } static unsigned int @@ -1513,32 +1171,38 @@ unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL); + lock_kernel(); if (minor == ISDN_MINOR_STATUS) { poll_wait(file, &(dev->info_waitq), wait); /* mask = POLLOUT | POLLWRNORM; */ if (file->private_data) { mask |= POLLIN | POLLRDNORM; } - return mask; + goto out; } if (minor >= ISDN_MINOR_CTRL && minor <= ISDN_MINOR_CTRLMAX) { if (drvidx < 0) { /* driver deregistered while file open */ - return POLLHUP; + mask = POLLHUP; + goto out; } poll_wait(file, &(dev->drv[drvidx]->st_waitq), wait); mask = POLLOUT | POLLWRNORM; if (dev->drv[drvidx]->stavail) { mask |= POLLIN | POLLRDNORM; } - return mask; + goto out; } #ifdef CONFIG_ISDN_PPP - if (minor <= ISDN_MINOR_PPPMAX) - return (isdn_ppp_poll(file, wait)); + if (minor <= ISDN_MINOR_PPPMAX) { + mask = isdn_ppp_poll(file, wait); + goto out; + } #endif - printk(KERN_ERR "isdn_common: isdn_poll 2 -> what the hell\n"); - return POLLERR; + mask = POLLERR; + out: + unlock_kernel(); + return mask; } @@ -2013,6 +1677,7 @@ if (!dev->channels) return -ENODEV; if (minor < ISDN_MINOR_CTRL) { + printk(KERN_WARNING "isdn_open minor %d obsolete!\n", minor); drvidx = isdn_minor2drv(minor); if (drvidx < 0) return -ENODEV; @@ -2091,7 +1756,7 @@ static struct file_operations isdn_fops = { owner: THIS_MODULE, - llseek: isdn_lseek, + llseek: isdn_llseek, read: isdn_read, write: isdn_write, poll: isdn_poll, @@ -2276,7 +1941,6 @@ skb_pull(nskb, sizeof(int)); if (!nskb->len) { dev_kfree_skb(nskb); - dev_kfree_skb(skb); return v110_ret; } /* V.110 must always be acknowledged */ @@ -2315,9 +1979,10 @@ atomic_inc(&dev->v110use[idx]); dev->v110[idx]->skbuser++; atomic_dec(&dev->v110use[idx]); - dev_kfree_skb(skb); /* For V.110 return unencoded data length */ ret = v110_ret; + /* if the complete frame was send we free the skb; + if not upper function will requeue the skb */ if (ret == skb->len) dev_kfree_skb(skb); } @@ -2639,7 +2304,7 @@ &isdn_fops, NULL); dev->devfs_handle_isdnctrl = devfs_register (devfs_handle, "isdnctrl", DEVFS_FL_DEFAULT, - ISDN_MAJOR, ISDN_MINOR_CTRL, 0600 | S_IFCHR, + ISDN_MAJOR, ISDN_MINOR_CTRL, 0600 | S_IFCHR, &isdn_fops, NULL); } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/isdn_common.h linux/drivers/isdn/isdn_common.h --- v2.4.0-test5/linux/drivers/isdn/isdn_common.h Wed Feb 16 17:03:52 2000 +++ linux/drivers/isdn/isdn_common.h Tue Aug 8 15:03:57 2000 @@ -1,4 +1,4 @@ -/* $Id: isdn_common.h,v 1.18 2000/01/23 18:45:37 keil Exp $ +/* $Id: isdn_common.h,v 1.20 2000/06/16 13:00:27 keil Exp $ * header for Linux ISDN subsystem, common used functions and debugging-switches (linklevel). * @@ -20,90 +20,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Log: isdn_common.h,v $ - * Revision 1.18 2000/01/23 18:45:37 keil - * Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN) - * - * Revision 1.17 1999/10/27 21:21:17 detabc - * Added support for building logically-bind-group's per interface. - * usefull for outgoing call's with more then one isdn-card. - * - * Switchable support to dont reset the hangup-timeout for - * receive frames. Most part's of the timru-rules for receiving frames - * are now obsolete. If the input- or forwarding-firewall deny - * the frame, the line will be not hold open. - * - * Revision 1.16 1999/07/01 08:29:54 keil - * compatibility to 2.3 kernel - * - * Revision 1.15 1999/04/18 14:06:50 fritz - * Removed TIMRU stuff. - * - * Revision 1.14 1999/04/12 12:33:18 fritz - * Changes from 2.0 tree. - * - * Revision 1.13 1999/03/02 12:04:47 armin - * -added ISDN_STAT_ADDCH to increase supported channels after - * register_isdn(). - * -ttyI now goes on-hook on ATZ when B-Ch is connected. - * -added timer-function for register S7 (Wait for Carrier). - * -analog modem (ISDN_PROTO_L2_MODEM) implementations. - * -on L2_MODEM a string will be appended to the CONNECT-Message, - * which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN. - * -variable "dialing" used for ATA also, for interrupting call - * establishment and register S7. - * - * Revision 1.12 1998/06/26 15:12:27 fritz - * Added handling of STAT_ICALL with incomplete CPN. - * Added AT&L for ttyI emulator. - * Added more locking stuff in tty_write. - * - * Revision 1.11 1998/04/14 16:28:47 he - * Fixed user space access with interrupts off and remaining - * copy_{to,from}_user() -> -EFAULT return codes - * - * Revision 1.10 1998/03/07 18:21:03 cal - * Dynamic Timeout-Rule-Handling vs. 971110 included - * - * Revision 1.9 1998/02/20 17:19:01 fritz - * Added common stub for sending commands to lowlevel. - * - * Revision 1.8 1997/10/09 21:28:49 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * New L1 error status (not yet in use). - * Cleaned up obsolete structures. - * Implemented Cisco-SLARP. - * Changed local net-interface data to be dynamically allocated. - * Removed old 2.0 compatibility stuff. - * - * Revision 1.7 1997/10/01 09:20:30 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.6 1997/02/28 02:32:44 fritz - * Cleanup: Moved some tty related stuff from isdn_common.c - * to isdn_tty.c - * Bugfix: Bisync protocol did not behave like documented. - * - * Revision 1.5 1997/02/10 10:05:45 fritz - * More changes for Kernel 2.1.X - * Symbol information moved to isdn_syms.c - * - * Revision 1.4 1997/02/03 22:56:50 fritz - * Removed isdn_writebuf_stub prototype. - * - * Revision 1.3 1996/05/19 00:13:05 fritz - * Removed debug flag. - * - * Revision 1.2 1996/04/20 16:20:40 fritz - * Misc. typos. - * - * Revision 1.1 1996/01/10 21:37:19 fritz - * Initial revision - * */ #undef ISDN_DEBUG_MODEM_OPEN @@ -134,7 +50,7 @@ extern int isdn_get_free_channel(int, int, int, int, int, char *); extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *); extern int register_isdn(isdn_if * i); -extern int isdn_wildmat(char *, char *); +extern int isdn_msncmp( const char *, const char *); extern int isdn_add_channels(driver *, int, int, int); #if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP) extern void isdn_dumppkt(char *, u_char *, int, int); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/isdn_concap.c linux/drivers/isdn/isdn_concap.c --- v2.4.0-test5/linux/drivers/isdn/isdn_concap.c Mon Mar 27 08:08:25 2000 +++ linux/drivers/isdn/isdn_concap.c Sun Aug 6 12:43:42 2000 @@ -1,35 +1,26 @@ -/* $Id: isdn_concap.c,v 1.7 2000/03/21 23:53:22 kai Exp $ +/* $Id: isdn_concap.c,v 1.8 2000/05/11 22:29:20 kai Exp $ - * Stuff to support the concap_proto by isdn4linux. isdn4linux - specific + * Linux ISDN subsystem, protocol encapsulation + * + * 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, 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. + * + */ + +/* Stuff to support the concap_proto by isdn4linux. isdn4linux - specific * stuff goes here. Stuff that depends only on the concap protocol goes to * another -- protocol specific -- source file. - * - * $Log: isdn_concap.c,v $ - * Revision 1.7 2000/03/21 23:53:22 kai - * fix backwards compatibility - * - * Revision 1.6 1999/08/22 20:26:01 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.5 1998/10/30 18:44:48 he - * pass return value from isdn_net_dial_req for dialmode change - * - * Revision 1.4 1998/10/30 17:55:24 he - * dialmode for x25iface and multulink ppp - * - * Revision 1.3 1998/05/26 22:39:22 he - * sync'ed with 2.1.102 where appropriate (CAPABILITY changes) - * concap typo - * cleared dev.tbusy in isdn_net BCONN status callback - * - * Revision 1.2 1998/01/31 22:49:21 keil - * correct comments - * - * Revision 1.1 1998/01/31 22:27:57 keil - * New files from Henner Eisen for X.25 support * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/isdn_concap.h linux/drivers/isdn/isdn_concap.h --- v2.4.0-test5/linux/drivers/isdn/isdn_concap.h Wed Apr 1 16:21:03 1998 +++ linux/drivers/isdn/isdn_concap.h Sun Aug 6 12:43:42 2000 @@ -1,5 +1,23 @@ -/* $Id: isdn_concap.h,v 1.2 1998/01/31 22:49:21 keil Exp $ +/* $Id: isdn_concap.h,v 1.3 2000/05/11 22:29:20 kai Exp $ + * + * Linux ISDN subsystem, protocol encapsulation + * + * 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, 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. + * */ + extern struct concap_device_ops isdn_concap_reliable_dl_dops; extern struct concap_device_ops isdn_concap_demand_dial_dops; extern struct concap_proto * isdn_concap_new( int ); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c --- v2.4.0-test5/linux/drivers/isdn/isdn_net.c Fri Jul 14 12:12:10 2000 +++ linux/drivers/isdn/isdn_net.c Tue Aug 8 15:03:57 2000 @@ -1,4 +1,4 @@ -/* $Id: isdn_net.c,v 1.125 2000/04/05 21:25:55 detabc Exp $ +/* $Id: isdn_net.c,v 1.134 2000/06/21 09:54:29 keil Exp $ * Linux ISDN subsystem, network interfaces and related functions (linklevel). * @@ -20,481 +20,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Log: isdn_net.c,v $ - * Revision 1.125 2000/04/05 21:25:55 detabc - * add leased-line support to abc-stuff - * - * Revision 1.124 2000/04/03 21:07:22 detabc - * change write_super handling for abc-stuff - * - * Revision 1.123 2000/04/03 19:14:36 kai - * fix "isdn BUG at isdn_net.c:1440!" - * - * Revision 1.122 2000/03/20 22:37:46 detabc - * modify abc-extension to work together with the new LL. - * remove abc frame-counter (is obsolete now). - * use the new lp->super_tx_queue for internal queueing (bsd-rawip-compress). - * modify isdn_net_xmit() and isdn_net_write_super(). - * -- Kai, please have a look to this two function's. Thank's. - * - * Revision 1.121 2000/03/19 15:27:53 kai - * no known bugs left... - * - * Revision 1.120 2000/03/18 16:20:25 kai - * cosmetics / renaming - * - * Revision 1.118 2000/03/17 18:20:46 kai - * moved to frame_cnt based flow control - * some races still need to be fixed - * - * Revision 1.117 2000/03/17 17:01:00 kai - * cleanup - * - * Revision 1.116 2000/03/17 16:22:55 kai - * we keep track of outstanding packets (given to HL, but not confirmed yet) - * now, but we don't use it for flow control yet. - * - * Revision 1.115 2000/03/17 12:49:42 kai - * calling statcallb with ISDN_STAT_BSENT in hard-IRQ context is now - * officially allowed. writebuf_skb() will never be called in hard-IRQ context - * anymore. - * - * Revision 1.114 2000/03/16 16:37:41 kai - * Allow phone numbers starting with "*" as outgoing numbers for - * networking interface. Some PBX's need this to allow dialing internal - * numbers (mine, for example ;-) - * - * Revision 1.113 2000/03/16 15:46:37 kai - * a little bugfix and cosmetic changes - * - * Revision 1.112 2000/03/04 16:20:42 detabc - * copy frames before rewriting frame's saddr - * - * Revision 1.111 2000/02/28 22:28:24 he - * moved tx_timeout warning messages in old (2.2.x) branch where it really only - * indicates problems. - * - * Revision 1.110 2000/02/26 01:00:53 keil - * changes from 2.3.47 - * - * Revision 1.109 2000/02/25 11:29:17 paul - * changed chargetime to ulong from int (after about 20 days the "chargetime of - * ipppX is now 1234" message displays a negative number on alpha). - * - * Revision 1.108 2000/02/15 12:54:01 kai - * set TX timeout back to 2 secs for 2.2.x, just to be safe - * - * Revision 1.107 2000/02/13 09:52:05 kai - * increased TX_TIMEOUT to 20sec - * - * Revision 1.106 2000/02/12 19:26:55 kai - * adopted to latest 2.3 softnet changes. - * - * tested with PPP and MPPP, it works here. - * can somebody check raw-ip? - * - * also changed std2kern, stddiff for bash-1 compatibility, - * hope this doesn't break anything. - * - * Revision 1.105 2000/02/12 11:43:26 he - * SOFTNET related changes, first try. Compatible with linux 2.2.x, but - * not tested for kernels with softnet (>= 2.3.43) yet. - * - * Revision 1.104 2000/02/06 21:49:59 detabc - * add rewriting of socket's and frame's saddr for udp-ipv4 dynip-connections. - * Include checksum-recompute of ip- and udp-header's. - * - * Revision 1.103 2000/01/23 18:45:37 keil - * Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN) - * - * Revision 1.102 2000/01/09 20:43:14 detabc - * exand logical bind-group's for both call's (in and out). - * add first part of kernel-config-help for abc-extension. - * - * Revision 1.101 1999/12/05 16:06:08 detabc - * add resethandling for rawip-compression. - * at now all B2-Protocols are usable with rawip-compression - * - * Revision 1.100 1999/12/04 15:05:25 detabc - * bugfix abc-rawip-bsdcompress with channel-bundeling - * - * Revision 1.99 1999/11/30 11:29:06 detabc - * add a on the fly frame-counter and limit - * - * Revision 1.98 1999/11/28 14:49:07 detabc - * In case of rawip-compress adjust dev[x]->ibytes/obytes to reflect the - * uncompressed size. - * - * Revision 1.97 1999/11/26 15:54:59 detabc - * added compression (isdn_bsdcompress) for rawip interfaces with x75i B2-protocol. - * - * Revision 1.96 1999/11/20 22:14:13 detabc - * added channel dial-skip in case of external use - * (isdn phone or another isdn device) on the same NTBA. - * usefull with two or more card's connected the different NTBA's. - * global switchable in kernel-config and also per netinterface. - * - * add auto disable of netinterface's in case of: - * to many connection's in short time. - * config mistakes (wrong encapsulation, B2-protokoll or so on) on local - * or remote side. - * wrong password's or something else to a ISP (syncppp). - * - * possible encapsulations for this future are: - * ISDN_NET_ENCAP_SYNCPPP, ISDN_NET_ENCAP_UIHDLC, ISDN_NET_ENCAP_RAWIP, - * and ISDN_NET_ENCAP_CISCOHDLCK. - * - * Revision 1.95 1999/10/27 21:21:17 detabc - * Added support for building logically-bind-group's per interface. - * usefull for outgoing call's with more then one isdn-card. - * - * Switchable support to dont reset the hangup-timeout for - * receive frames. Most part's of the timru-rules for receiving frames - * are now obsolete. If the input- or forwarding-firewall deny - * the frame, the line will be not hold open. - * - * Revision 1.94 1999/10/02 11:07:02 he - * Changed tbusy logic in indn_net.c - * - * Revision 1.93 1999/09/23 22:22:41 detabc - * added tcp-keepalive-detect with local response (ipv4 only) - * added host-only-interface support - * (source ipaddr == interface ipaddr) (ipv4 only) - * ok with kernel 2.3.18 and 2.2.12 - * - * Revision 1.92 1999/09/13 23:25:17 he - * serialized xmitting frames from isdn_ppp and BSENT statcallb - * - * Revision 1.91 1999/09/12 16:19:39 detabc - * added abc features - * low cost routing for net-interfaces (only the HL side). - * need more implementation in the isdnlog-utility - * udp info support (first part). - * different EAZ on outgoing call's. - * more checks on D-Channel callbacks (double use of channels). - * tested and running with kernel 2.3.17 - * - * Revision 1.90 1999/09/04 22:21:39 detabc - * - * Revision 1.89 1999/08/22 20:26:03 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.88 1999/07/07 10:13:31 detabc - * remove unused messages - * - * Revision 1.87 1999/07/06 07:53:53 calle - * calls to dev_alloc_skb waste 16 bytes of memory, if we calculate the - * right header space for the lowlevel driver. using alloc_skb instead. - * - * Revision 1.86 1999/06/09 10:12:05 paul - * thinko in previous patch - * - * Revision 1.85 1999/06/07 19:42:39 paul - * isdn_net_getpeer() fixed to return correct `outgoing' flag - * - * Revision 1.84 1999/04/18 14:06:55 fritz - * Removed TIMRU stuff. - * - * Revision 1.83 1999/04/12 12:33:23 fritz - * Changes from 2.0 tree. - * - * Revision 1.82 1999/01/17 00:55:58 he - * added mark_bh in BCONN statcallb and cleaned up some dead code - * - * Revision 1.81 1999/01/15 16:36:52 he - * replaced icmp_send() by dst_link_failure() - * - * Revision 1.80 1998/12/01 13:06:22 paul - * Also huptimeout with dialmode == manual - * - * Revision 1.79 1998/10/30 17:55:27 he - * dialmode for x25iface and multulink ppp - * - * Revision 1.78 1998/10/26 18:20:46 he - * re-inserted p=p->next in isdn_net_find_icall() (fixes kernel lock up - * on incoming call not matching the first interface) - * - * Revision 1.77 1998/10/23 10:18:44 paul - * Implementation of "dialmode" (successor of "status") - * You also need current isdnctrl for this! - * - * Revision 1.76 1998/09/07 22:00:05 he - * flush method for 2.1.118 and above - * updated IIOCTLNETGPN - * - * Revision 1.75 1998/08/31 21:09:50 he - * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface' - * peer phone number) - * - * Revision 1.74 1998/07/30 11:28:32 paul - * printk message only appeared when status is off and interface is rawIP, - * which is confusing for people who don't know about "isdnctrl status on". - * - * Revision 1.73 1998/06/26 22:01:37 keil - * tx_queue_len = 5 was too small - * - * Revision 1.72 1998/06/26 15:12:31 fritz - * Added handling of STAT_ICALL with incomplete CPN. - * Added AT&L for ttyI emulator. - * Added more locking stuff in tty_write. - * - * Revision 1.71 1998/06/18 22:43:08 fritz - * Bugfix: Setting ndev->do_ioctl had beed accidetly removed at cleanup. - * - * Revision 1.70 1998/06/17 19:50:49 he - * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay()) - * brute force fix to avoid Ugh's in isdn_tty_write() - * cleaned up some dead code - * - * Revision 1.69 1998/06/09 12:27:37 cal - * Changed default of local netdev flags: ISDN_NET_STOPPED is default now, - * so autodial is suppressed for that device until it is switched on using - * 'isdnctrl status dev-name on'. - * - * - * - * Revision 1.66 1998/05/26 22:39:24 he - * sync'ed with 2.1.102 where appropriate (CAPABILITY changes) - * concap typo - * cleared dev.tbusy in isdn_net BCONN status callback - * - * Revision 1.61 1998/04/16 19:19:42 keil - * Fix from vger (tx max qlength) - * - * Revision 1.60 1998/04/14 16:28:49 he - * Fixed user space access with interrupts off and remaining - * copy_{to,from}_user() -> -EFAULT return codes - * - * Revision 1.59 1998/03/07 22:37:33 fritz - * Bugfix: restore_flags missing. - * - * Revision 1.58 1998/03/07 18:21:05 cal - * Dynamic Timeout-Rule-Handling vs. 971110 included - * - * Revision 1.57 1998/02/25 18:31:13 fritz - * Added debugging output in adjust_header. - * - * Revision 1.56 1998/02/25 17:49:42 he - * Changed return codes caused be failing copy_{to,from}_user to -EFAULT - * - * Revision 1.55 1998/02/23 19:38:22 fritz - * Corrected check for modified feature-flags. - * - * Revision 1.54 1998/02/20 17:15:07 fritz - * Changes for recent kernels. - * Ugly workaround for adjusting Ethernet frames with recent kernels. - * replaced direct calls to lowlevel-driver command by common hook. - * - * Revision 1.53 1998/01/31 22:05:54 keil - * Lots of changes for X.25 support: - * Added generic support for connection-controlling encapsulation protocols - * Added support of BHUP status message - * Added support for additional p_encap X25IFACE - * Added support for kernels >= 2.1.72 - * - * Revision 1.52 1998/01/31 19:29:51 calle - * Merged changes from and for 2.1.82, not tested only compiled ... - * - * Revision 1.51 1997/10/09 21:28:50 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * New L1 error status (not yet in use). - * Cleaned up obsolete structures. - * Implemented Cisco-SLARP. - * Changed local net-interface data to be dynamically allocated. - * Removed old 2.0 compatibility stuff. - * - * Revision 1.50 1997/10/01 09:20:32 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.49 1997/08/21 14:38:13 fritz - * Bugfix: Did not compile without SyncPPP. - * - * Revision 1.48 1997/06/22 11:57:15 fritz - * Added ability to adjust slave triggerlevel. - * - * Revision 1.47 1997/06/21 10:52:05 fritz - * Removed wrong SET_SKB_FREE in isdn_net_send_skb() - * - * Revision 1.46 1997/06/17 13:05:24 hipp - * Applied Eric's underflow-patches (slightly modified) - * - * Revision 1.45 1997/06/10 16:24:22 hipp - * hard_header changes for syncPPP (now behaves like RAWIP) - * - * Revision 1.44 1997/05/27 15:17:26 fritz - * Added changes for recent 2.1.x kernels: - * changed return type of isdn_close - * queue_task_* -> queue_task - * clear/set_bit -> test_and_... where apropriate. - * changed type of hard_header_cache parameter. - * - * Revision 1.43 1997/03/30 16:51:13 calle - * changed calls to copy_from_user/copy_to_user and removed verify_area - * were possible. - * - * Revision 1.42 1997/03/11 08:43:51 fritz - * Perform a hangup if number is deleted while dialing. - * - * Revision 1.41 1997/03/08 08:16:31 fritz - * Bugfix: Deleting a phone number during dial gave unpredictable results. - * - * Revision 1.40 1997/03/05 21:16:08 fritz - * Fix: did not compile with 2.1.27 - * - * Revision 1.39 1997/03/04 21:36:52 fritz - * Added sending ICMP messages when no connetion is possible. - * - * Revision 1.38 1997/02/23 23:41:14 fritz - * Bugfix: Slave interfaces have to be hung up before master. - * - * Revision 1.37 1997/02/11 18:32:51 fritz - * Bugfix in isdn_ppp_free_mpqueue(). - * - * Revision 1.36 1997/02/10 21:31:11 fritz - * Changed setup-interface (incoming and outgoing). - * - * Revision 1.35 1997/02/10 20:12:45 fritz - * Changed interface for reporting incoming calls. - * - * Revision 1.34 1997/02/03 23:15:07 fritz - * Reformatted according CodingStyle. - * replaced arp_find prototype by proper include. - * made dev_purge_queues static. - * Bugfix in bogocps calculation. - * removed isdn_net_receive_callback - was never used ;-) - * Misc. fixes for Kernel 2.1.X comaptibility. - * - * Revision 1.33 1997/01/17 01:19:25 fritz - * Applied chargeint patch. - * - * Revision 1.32 1997/01/14 01:29:31 fritz - * Bugfix: isdn_net_hangup() did not reset ISDN_NET_CONNECTED. - * - * Revision 1.31 1997/01/11 23:30:42 fritz - * Speed up dial statemachine. - * - * Revision 1.30 1996/11/25 17:20:50 hipp - * fixed pppbind bug in isdn_net_find_icall() - * - * Revision 1.29 1996/11/13 02:31:38 fritz - * Minor cleanup. - * - * Revision 1.28 1996/10/27 20:49:06 keil - * bugfix to compile without MPP - * - * Revision 1.27 1996/10/25 18:46:01 fritz - * Another bugfix in isdn_net_autohup() - * - * Revision 1.26 1996/10/23 23:05:36 fritz - * Bugfix: Divide by zero in isdn_net_autohup() - * - * Revision 1.25 1996/10/22 23:13:58 fritz - * Changes for compatibility to 2.0.X and 2.1.X kernels. - * - * Revision 1.24 1996/10/11 13:57:40 fritz - * Bugfix: Error in BogoCPS calculation. - * - * Revision 1.23 1996/09/23 01:58:08 fritz - * Fix: With syncPPP encapsulation, discard LCP packets - * when calculating hangup timeout. - * - * Revision 1.22 1996/09/23 00:03:37 fritz - * Fix: did not compile without CONFIG_ISDN_PPP - * - * Revision 1.21 1996/09/07 12:44:50 hipp - * (hopefully) fixed callback problem with syncPPP - * syncPPP network devices now show PPP link encap - * - * Revision 1.20 1996/08/29 20:06:03 fritz - * Bugfix: Transmission timeout had been much to low. - * - * Revision 1.19 1996/08/12 16:24:32 hipp - * removed some (now) obsolete functions for syncPPP in rebuild_header etc. - * - * Revision 1.18 1996/07/03 13:48:51 hipp - * bugfix: Call dev_purge_queues() only for master device - * - * Revision 1.17 1996/06/25 18:37:37 fritz - * Fixed return count for empty return string in isdn_net_getphones(). - * - * Revision 1.16 1996/06/24 17:48:08 fritz - * Bugfixes: - * - Did not free channel on unbinding. - * - ioctl returned wrong callback settings. - * - * Revision 1.15 1996/06/16 17:42:54 tsbogend - * fixed problem with IP addresses on Linux/Alpha (long is 8 byte there) - * - * Revision 1.14 1996/06/11 14:54:08 hipp - * minor bugfix in isdn_net_send_skb - * changes in BSENT callback handler for syncPPP - * added lp->sav_skb stuff - * - * Revision 1.13 1996/06/06 14:25:44 fritz - * Changed loglevel of "incoming ... without OAD" message, since - * with audio support this is quite normal. - * - * Revision 1.12 1996/06/05 02:36:45 fritz - * Minor bugfixes by M. Hipp. - * - * Revision 1.11 1996/05/18 01:36:59 fritz - * Added spelling corrections and some minor changes - * to stay in sync with kernel. - * - * Revision 1.10 1996/05/17 03:49:01 fritz - * Some cleanup. - * - * Revision 1.9 1996/05/06 11:34:57 hipp - * fixed a few bugs - * - * Revision 1.8 1996/04/30 21:04:40 fritz - * Test commit - * - * Revision 1.7 1996/04/30 11:10:42 fritz - * Added Michael's ippp-bind patch. - * - * Revision 1.6 1996/04/30 09:34:35 fritz - * Removed compatibility-macros. - * - * Revision 1.5 1996/04/20 16:28:38 fritz - * Made more parameters of the dial statemachine user-configurable and - * added hangup after dial for more reliability using callback. - * Changed all io going through generic routines in isdn_common.c - * Added missing call to dev_free_skb on failed dialing. - * Added uihdlc encapsulation. - * Fixed isdn_net_setcfg not to destroy interface-flags anymore. - * Misc. typos. - * - * Revision 1.4 1996/02/19 15:23:38 fritz - * Bugfix: Sync-PPP packets got compressed twice, when resent due to - * send-queue-full reject. - * - * Revision 1.3 1996/02/11 02:22:28 fritz - * Changed status- receive-callbacks to use pointer-arrays for finding - * a corresponding interface instead of looping over all interfaces. - * Activate Auto-hangup-timer only when interface is online. - * Some bugfixes in the dialing-statemachine. - * Lot of bugfixes in sk_buff'ized encapsulation handling. - * For speedup connection-setup after dialing, remember sk_buf that triggered - * dialing. - * Fixed isdn_net_log_packet according to different encapsulations. - * Correct ARP-handling for ETHERNET-encapsulation. - * - * Revision 1.2 1996/01/22 05:05:12 fritz - * Changed returncode-logic for isdn_net_start_xmit() and its - * helper-functions. - * Changed handling of buildheader for RAWIP and ETHERNET-encapsulation. - * - * Revision 1.1 1996/01/09 04:12:34 fritz - * Initial revision - * */ #include @@ -656,7 +181,7 @@ int isdn_net_force_dial_lp(isdn_net_local *); static int isdn_net_start_xmit(struct sk_buff *, struct net_device *); -char *isdn_net_revision = "$Revision: 1.125 $"; +char *isdn_net_revision = "$Revision: 1.134 $"; /* * Code for raw-networking over ISDN @@ -930,7 +455,8 @@ #endif /* CONFIG_ISDN_X25 */ if ((!lp->dialstate) && (lp->flags & ISDN_NET_CONNECTED)) { #ifdef CONFIG_ISDN_PPP - isdn_ppp_free(lp); + if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) + isdn_ppp_free(lp); #endif isdn_net_lp_disconnected(lp); isdn_all_eaz(lp->isdn_device, lp->isdn_channel); @@ -1322,9 +848,19 @@ #endif if (lp->flags & ISDN_NET_CONNECTED) { + if (lp->slave != NULL) { + isdn_net_local *slp = (isdn_net_local *)lp->slave->priv; + if (slp->flags & ISDN_NET_CONNECTED) { + printk(KERN_INFO + "isdn_net: hang up slave %s before %s\n", + slp->name, lp->name); + isdn_net_hangup(lp->slave); + } + } printk(KERN_INFO "isdn_net: local hangup %s\n", lp->name); #ifdef CONFIG_ISDN_PPP - isdn_ppp_free(lp); + if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) + isdn_ppp_free(lp); #endif isdn_net_lp_disconnected(lp); #ifdef CONFIG_ISDN_X25 @@ -1454,8 +990,7 @@ } spin_lock_bh(&lp->xmit_lock); - if (!isdn_net_lp_busy(lp)) - { + if (!isdn_net_lp_busy(lp)) { isdn_net_writebuf_skb(lp, skb); } else { skb_queue_tail(&lp->super_tx_queue, skb); @@ -1556,7 +1091,7 @@ lp = isdn_net_get_locked_lp(nd); if (!lp) { - printk(KERN_WARNING "%s: all channels busy - requeuing!\n", lp->name); + printk(KERN_WARNING "%s: all channels busy - requeuing!\n", ndev->name); return 1; } /* we have our lp locked from now on */ @@ -2369,7 +1904,7 @@ * would eventually match if CID was longer. */ int -isdn_net_find_icall(int di, int ch, int idx, setup_parm setup) +isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) { char *eaz; int si1; @@ -2385,19 +1920,19 @@ /* Search name in netdev-chain */ save_flags(flags); cli(); - if (!setup.phone[0]) { + if (!setup->phone[0]) { nr[0] = '0'; nr[1] = '\0'; printk(KERN_INFO "isdn_net: Incoming call without OAD, assuming '0'\n"); } else - strcpy(nr, setup.phone); - si1 = (int) setup.si1; - si2 = (int) setup.si2; - if (!setup.eazmsn[0]) { + strcpy(nr, setup->phone); + si1 = (int) setup->si1; + si2 = (int) setup->si2; + if (!setup->eazmsn[0]) { printk(KERN_WARNING "isdn_net: Incoming call without CPN, assuming '0'\n"); eaz = "0"; } else - eaz = setup.eazmsn; + eaz = setup->eazmsn; if (dev->net_verbose > 1) printk(KERN_INFO "isdn_net: call from %s,%d,%d -> %s\n", nr, si1, si2, eaz); /* Accept only calls with Si1 = 7 (Data-Transmission) */ @@ -2428,7 +1963,7 @@ break; } swapped = 0; - if (!(matchret = isdn_wildmat(eaz, isdn_map_eaz2msn(lp->msn, di)))) + if (!(matchret = isdn_msncmp(eaz, isdn_map_eaz2msn(lp->msn, di)))) ematch = 1; /* Remember if more numbers eventually can match */ if (matchret > wret) @@ -2520,7 +2055,7 @@ n = lp->phone[0]; if (lp->flags & ISDN_NET_SECURE) { while (n) { - if (!isdn_wildmat(nr, n->num)) + if (!isdn_msncmp(nr, n->num)) break; n = (isdn_net_phone *) n->next; } @@ -2831,11 +2366,6 @@ } netdev->local->magic = ISDN_NET_MAGIC; -#ifdef CONFIG_ISDN_PPP - netdev->mp_last = NULL; /* mpqueue is empty */ - netdev->ib.next_num = 0; - netdev->ib.last = NULL; -#endif netdev->queue = netdev->local; spin_lock_init(&netdev->queue_lock); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/isdn_net.h linux/drivers/isdn/isdn_net.h --- v2.4.0-test5/linux/drivers/isdn/isdn_net.h Mon Mar 27 08:08:25 2000 +++ linux/drivers/isdn/isdn_net.h Tue Aug 8 15:03:57 2000 @@ -1,4 +1,4 @@ -/* $Id: isdn_net.h,v 1.16 2000/03/21 23:53:22 kai Exp $ +/* $Id: isdn_net.h,v 1.19 2000/06/21 09:54:29 keil Exp $ * header for Linux ISDN subsystem, network related functions (linklevel). * @@ -20,68 +20,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Log: isdn_net.h,v $ - * Revision 1.16 2000/03/21 23:53:22 kai - * fix backwards compatibility - * - * Revision 1.15 2000/03/19 15:27:53 kai - * no known bugs left... - * - * Revision 1.14 2000/03/18 16:20:25 kai - * cosmetics / renaming - * - * Revision 1.13 2000/03/17 18:20:46 kai - * moved to frame_cnt based flow control - * some races still need to be fixed - * - * Revision 1.12 2000/03/17 17:01:00 kai - * cleanup - * - * Revision 1.11 2000/03/17 16:22:55 kai - * we keep track of outstanding packets (given to HL, but not confirmed yet) - * now, but we don't use it for flow control yet. - * - * Revision 1.10 1999/08/22 20:26:06 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.9 1999/04/12 12:33:27 fritz - * Changes from 2.0 tree. - * - * Revision 1.8 1998/10/30 17:55:33 he - * dialmode for x25iface and multulink ppp - * - * Revision 1.7 1998/08/31 21:09:55 he - * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface' - * peer phone number) - * - * Revision 1.6 1997/10/09 21:28:54 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * New L1 error status (not yet in use). - * Cleaned up obsolete structures. - * Implemented Cisco-SLARP. - * Changed local net-interface data to be dynamically allocated. - * Removed old 2.0 compatibility stuff. - * - * Revision 1.5 1997/02/10 20:12:47 fritz - * Changed interface for reporting incoming calls. - * - * Revision 1.4 1997/02/03 23:16:48 fritz - * Removed isdn_net_receive_callback prototype. - * - * Revision 1.3 1997/01/17 01:19:30 fritz - * Applied chargeint patch. - * - * Revision 1.2 1996/04/20 16:29:43 fritz - * Misc. typos - * - * Revision 1.1 1996/02/11 02:35:13 fritz - * Initial revision - * */ /* Definitions for hupflags: */ @@ -137,7 +75,7 @@ extern int isdn_net_getphones(isdn_net_ioctl_phone *, char *); extern int isdn_net_getpeer(isdn_net_ioctl_phone *, isdn_net_ioctl_phone *); extern int isdn_net_delphone(isdn_net_ioctl_phone *); -extern int isdn_net_find_icall(int, int, int, setup_parm); +extern int isdn_net_find_icall(int, int, int, setup_parm *); extern void isdn_net_hangup(struct net_device *); extern void isdn_net_dial(void); extern void isdn_net_autohup(void); @@ -178,13 +116,15 @@ while (isdn_net_lp_busy(nd->queue)) { spin_unlock_bh(&nd->queue->xmit_lock); nd->queue = nd->queue->next; - if (nd->queue == lp) /* not found -- should never happen */ - return 0; + if (nd->queue == lp) { /* not found -- should never happen */ + lp = NULL; + goto errout; + } spin_lock_bh(&nd->queue->xmit_lock); } lp = nd->queue; - nd->queue = nd->queue->next; +errout: spin_unlock_irqrestore(&nd->queue_lock, flags); return lp; } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c --- v2.4.0-test5/linux/drivers/isdn/isdn_ppp.c Mon Mar 27 08:08:25 2000 +++ linux/drivers/isdn/isdn_ppp.c Tue Aug 8 15:03:57 2000 @@ -1,4 +1,4 @@ -/* $Id: isdn_ppp.c,v 1.69 2000/03/19 15:27:53 kai Exp $ +/* $Id: isdn_ppp.c,v 1.77 2000/06/12 16:46:34 keil Exp $ * * Linux ISDN subsystem, functions for synchronous PPP (linklevel). * @@ -18,273 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Log: isdn_ppp.c,v $ - * Revision 1.69 2000/03/19 15:27:53 kai - * no known bugs left... - * - * Revision 1.67 2000/03/17 18:20:46 kai - * moved to frame_cnt based flow control - * some races still need to be fixed - * - * Revision 1.66 2000/03/17 17:01:00 kai - * cleanup - * - * Revision 1.65 2000/03/17 16:22:55 kai - * we keep track of outstanding packets (given to HL, but not confirmed yet) - * now, but we don't use it for flow control yet. - * - * Revision 1.64 2000/03/17 10:43:56 kai - * 2.3.99 contains MPPP constants which cause a warning because we - * redefine them in include/linux/isdn_ppp.h - * - * So from now on we use the generic PPP constants, change is backwards - * compatible, though - * - * Revision 1.63 2000/03/16 15:46:37 kai - * a little bugfix and cosmetic changes - * - * Revision 1.62 2000/02/12 19:26:55 kai - * adopted to latest 2.3 softnet changes. - * - * tested with PPP and MPPP, it works here. - * can somebody check raw-ip? - * - * also changed std2kern, stddiff for bash-1 compatibility, - * hope this doesn't break anything. - * - * Revision 1.61 1999/11/20 22:14:14 detabc - * added channel dial-skip in case of external use - * (isdn phone or another isdn device) on the same NTBA. - * usefull with two or more card's connected the different NTBA's. - * global switchable in kernel-config and also per netinterface. - * - * add auto disable of netinterface's in case of: - * to many connection's in short time. - * config mistakes (wrong encapsulation, B2-protokoll or so on) on local - * or remote side. - * wrong password's or something else to a ISP (syncppp). - * - * possible encapsulations for this future are: - * ISDN_NET_ENCAP_SYNCPPP, ISDN_NET_ENCAP_UIHDLC, ISDN_NET_ENCAP_RAWIP, - * and ISDN_NET_ENCAP_CISCOHDLCK. - * - * Revision 1.60 1999/11/04 20:29:55 he - * applied Andre Beck's reset_free fix - * - * Revision 1.59 1999/10/31 15:59:50 he - * more skb headroom checks - * - * Revision 1.58 1999/10/30 13:13:01 keil - * Henners isdn_ppp_skb_push:under fix - * - * Revision 1.57 1999/10/05 22:47:17 he - * Removed dead ISDN_SYNCPPP_READDRESS code (obsoleted by sysctl_ip_dynaddr - * and network address translation) - * - * Revision 1.56 1999/09/29 16:01:06 he - * replaced dev_alloc_skb() for downstream skbs by equivalent alloc_skb() - * - * Revision 1.55 1999/09/23 22:07:51 detabc - * - * make ipc_head common usable (for use compressor with raw-ip) - * add function before netif_rx(). needed for ipv4-tcp-keepalive-detect. - * ~ - * - * Revision 1.54 1999/09/13 23:25:17 he - * serialized xmitting frames from isdn_ppp and BSENT statcallb - * - * Revision 1.53 1999/08/31 11:18:14 paul - * various spelling corrections (new checksums may be needed, Karsten!) - * - * Revision 1.52 1999/08/22 20:26:07 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.51 1999/08/18 16:19:17 hipp - * applied MPPP-resize-headroom patch - * - * Revision 1.50 1999/08/16 07:11:41 hipp - * Additional VJ decomp-buffer-size increased from 40 to 128 - * - * Revision 1.49 1999/07/06 07:47:11 calle - * bugfix: dev_alloc_skb only reserve 16 bytes. We need to look at the - * hdrlen the driver want. So I changed dev_alloc_skb calls - * to alloc_skb and skb_reserve. - * - * Revision 1.48 1999/07/01 08:29:56 keil - * compatibility to 2.3 kernel - * - * Revision 1.47 1999/04/18 14:06:59 fritz - * Removed TIMRU stuff. - * - * Revision 1.46 1999/04/12 12:33:35 fritz - * Changes from 2.0 tree. - * - * Revision 1.45 1998/12/30 17:48:24 paul - * fixed syncPPP callback out - * - * Revision 1.44 1998/10/30 17:55:34 he - * dialmode for x25iface and multulink ppp - * - * Revision 1.43 1998/10/29 17:23:54 hipp - * Minor MPPP fixes, verboser logging. - * - * Revision 1.42 1998/07/20 11:30:07 hipp - * Readded compression check - * - * Revision 1.41 1998/07/08 16:50:57 hipp - * Compression changes - * - * Revision 1.40 1998/04/06 19:07:27 hipp - * added check, whether compression is enabled. - * - * Revision 1.39 1998/03/25 22:46:53 hipp - * Some additional CCP changes. - * - * Revision 1.38 1998/03/24 16:33:06 hipp - * More CCP changes. BSD compression now "works" on a local loopback link. - * Moved some isdn_ppp stuff from isdn.h to isdn_ppp.h - * - * Revision 1.37 1998/03/22 18:50:49 hipp - * Added BSD Compression for syncPPP .. UNTESTED at the moment - * - * Revision 1.36 1998/03/09 17:46:30 he - * merged in 2.1.89 changes - * - * Revision 1.35 1998/03/07 18:21:11 cal - * Dynamic Timeout-Rule-Handling vs. 971110 included - * - * Revision 1.34 1998/02/25 17:49:48 he - * Changed return codes caused be failing copy_{to,from}_user to -EFAULT - * - * Revision 1.33 1998/02/20 17:11:54 fritz - * Changes for recent kernels. - * - * Revision 1.32 1998/01/31 19:29:55 calle - * Merged changes from and for 2.1.82, not tested only compiled ... - * - * Revision 1.31 1997/10/09 21:29:01 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * New L1 error status (not yet in use). - * Cleaned up obsolete structures. - * Implemented Cisco-SLARP. - * Changed local net-interface data to be dynamically allocated. - * Removed old 2.0 compatibility stuff. - * - * Revision 1.30 1997/10/01 09:20:38 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.29 1997/08/21 23:11:44 fritz - * Added changes for kernels >= 2.1.45 - * - * Revision 1.28 1997/06/17 13:05:57 hipp - * Applied Eric's underflow-patches (slightly modified) - * more compression changes (but disabled at the moment) - * changed one copy_to_user() to run with enabled IRQs - * a few MP changes - * changed 'proto' handling in the isdn_ppp receive code - * - * Revision 1.27 1997/03/30 16:51:17 calle - * changed calls to copy_from_user/copy_to_user and removed verify_area - * were possible. - * - * Revision 1.26 1997/02/23 16:53:44 hipp - * minor cleanup - * some initial changes for future PPP compresion - * added AC,PC compression for outgoing frames - * - * Revision 1.25 1997/02/12 20:37:35 hipp - * New ioctl() PPPIOCGCALLINFO, minor cleanup - * - * Revision 1.24 1997/02/11 18:32:56 fritz - * Bugfix in isdn_ppp_free_mpqueue(). - * - * Revision 1.23 1997/02/10 11:12:19 fritz - * More changes for Kernel 2.1.X compatibility. - * - * Revision 1.22 1997/02/06 15:03:51 hipp - * changed GFP_KERNEL kmalloc to GFP_ATOMIC in isdn_ppp_fill_mpqueue() - * - * Revision 1.21 1997/02/03 23:29:38 fritz - * Reformatted according CodingStyle - * Bugfix: removed isdn_ppp_skb_destructor, used by upper layers. - * Misc changes for Kernel 2.1.X compatibility. - * - * Revision 1.20 1996/10/30 12:21:58 fritz - * Cosmetic fix: Compiler warning when compiling without MPP. - * - * Revision 1.19 1996/10/25 19:03:21 hipp - * changed/added some defines to (re)allow compilation without MP/VJ - * - * Revision 1.18 1996/10/22 23:14:00 fritz - * Changes for compatibility to 2.0.X and 2.1.X kernels. - * - * Revision 1.17 1996/10/22 09:39:49 hipp - * a few MP changes and bugfixes - * - * Revision 1.16 1996/09/23 01:58:10 fritz - * Fix: With syncPPP encapsulation, discard LCP packets - * when calculating hangup timeout. - * - * Revision 1.15 1996/09/07 12:50:12 hipp - * bugfixes (unknown device after failed dial attempt, minor bugs) - * - * Revision 1.14 1996/08/12 16:26:47 hipp - * code cleanup - * changed connection management from minors to slots - * - * Revision 1.13 1996/07/01 19:47:24 hipp - * Fixed memory leak in VJ handling and more VJ changes - * - * Revision 1.12 1996/06/24 17:42:03 fritz - * Minor bugfixes. - * - * Revision 1.11 1996/06/16 17:46:05 tsbogend - * changed unsigned long to u32 to make Alpha people happy - * - * Revision 1.10 1996/06/11 14:50:29 hipp - * Lot of changes and bugfixes. - * New scheme to resend packets to busy LL devices. - * - * Revision 1.9 1996/05/18 01:37:01 fritz - * Added spelling corrections and some minor changes - * to stay in sync with kernel. - * - * Revision 1.8 1996/05/06 11:34:55 hipp - * fixed a few bugs - * - * Revision 1.7 1996/04/30 11:07:42 fritz - * Added Michael's ippp-bind patch. - * - * Revision 1.6 1996/04/30 09:33:09 fritz - * Removed compatibility-macros. - * - * Revision 1.5 1996/04/20 16:32:32 fritz - * Changed ippp_table to an array of pointers, allocating each part - * separately. - * - * Revision 1.4 1996/02/19 15:25:50 fritz - * Bugfix: Sync-PPP packets got compressed twice, when resent due to - * send-queue-full reject. - * - * Revision 1.3 1996/02/11 02:27:12 fritz - * Lot of Bugfixes my Michael. - * Moved calls to skb_push() into isdn_net_header() - * Fixed a possible race-condition in isdn_ppp_timer_timeout(). - * - * Revision 1.2 1996/01/22 05:08:06 fritz - * Merged in Michael's patches for MP. - * Minor changes in isdn_ppp_xmit. - * - * Revision 1.1 1996/01/09 04:11:29 fritz - * Initial revision - * */ #include @@ -341,17 +74,18 @@ #ifdef CONFIG_ISDN_MPP -static int isdn_ppp_bundle(struct ippp_struct *, int unit); -static void isdn_ppp_mask_queue(isdn_net_dev * dev, long mask); -static void isdn_ppp_cleanup_mpqueue(isdn_net_dev * dev, long min); -static void isdn_ppp_cleanup_sqqueue(isdn_net_dev * dev, isdn_net_local *, long min); -static void isdn_ppp_free_sqqueue(isdn_net_dev *); -static int isdn_ppp_fill_mpqueue(isdn_net_dev *, struct sk_buff **skb, - int BEbyte, long *sqno, int min_sqno); -static void isdn_ppp_free_mpqueue(isdn_net_dev *); -#endif +static ippp_bundle * isdn_ppp_bundle_arr = NULL; + +static int isdn_ppp_mp_bundle_array_init(void); +static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to ); +static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, + struct sk_buff *skb); +static void isdn_ppp_mp_cleanup( isdn_net_local * lp ); -char *isdn_ppp_revision = "$Revision: 1.69 $"; +static int isdn_ppp_bundle(struct ippp_struct *, int unit); +#endif /* CONFIG_ISDN_MPP */ + +char *isdn_ppp_revision = "$Revision: 1.77 $"; static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS]; @@ -386,7 +120,6 @@ int isdn_ppp_free(isdn_net_local * lp) { - isdn_net_local *master_lp = lp; unsigned long flags; struct ippp_struct *is; @@ -397,17 +130,18 @@ cli(); #ifdef CONFIG_ISDN_MPP - if (lp->next == lp) { /* last link in queue? */ - master_lp->netdev->ib.bundled = 0; - isdn_ppp_free_mpqueue(master_lp->netdev); - isdn_ppp_free_sqqueue(master_lp->netdev); - } + spin_lock(&lp->netdev->pb->lock); #endif - isdn_net_rm_from_bundle(lp); +#ifdef CONFIG_ISDN_MPP + if (lp->netdev->pb->ref_ct == 1) /* last link in queue? */ + isdn_ppp_mp_cleanup(lp); + + lp->netdev->pb->ref_ct--; + spin_unlock(&lp->netdev->pb->lock); +#endif /* CONFIG_ISDN_MPP */ is = ippp_table[lp->ppp_slot]; - if ((is->state & IPPP_CONNECT)) isdn_ppp_closewait(lp->ppp_slot); /* force wakeup on ippp device */ else if (is->state & IPPP_ASSIGNED) @@ -420,7 +154,6 @@ lp->ppp_slot = -1; /* is this OK ?? */ restore_flags(flags); - return 0; } @@ -437,7 +170,6 @@ save_flags(flags); cli(); - if (lp->pppbind < 0) { /* device bounded to ippp device ? */ isdn_net_dev *net_dev = dev->netdev; char exclusive[ISDN_MAX_CHANNELS]; /* exclusive flags */ @@ -474,20 +206,16 @@ printk(KERN_ERR "isdn_ppp_bind: illegal interface name %s.\n", lp->name); return -1; } + lp->ppp_slot = i; - - /* reset some values */ - lp->netdev->ib.bundled = 0; - lp->netdev->ib.next_num = 0; - lp->netdev->ib.modify = 0; - lp->netdev->ib.last = NULL; - lp->netdev->ib.min = 0; - lp->netdev->ib.sq = NULL; - is = ippp_table[i]; is->lp = lp; is->unit = unit; is->state = IPPP_OPEN | IPPP_ASSIGNED; /* assigned to a netdevice but not connected */ +#ifdef CONFIG_ISDN_MPP + if (isdn_ppp_mp_init(lp, NULL) < 0) + return -ENOMEM; +#endif /* CONFIG_ISDN_MPP */ restore_flags(flags); @@ -580,7 +308,6 @@ is->mp_seqno = 0; /* MP sequence number */ is->pppcfg = 0; /* ppp configuration */ is->mpppcfg = 0; /* mppp configuration */ - is->range = 0x1000000; /* MP: 24 bit range */ is->last_link_seqno = -1; /* MP: maybe set to Bundle-MIN, when joining a bundle ?? */ is->unit = -1; /* set, when we have our interface */ is->mru = 1524; /* MRU, default 1524 */ @@ -1077,6 +804,11 @@ { int i, j; + +#ifdef CONFIG_ISDN_MPP + if( isdn_ppp_mp_bundle_array_init() < 0 ) + return -ENOMEM; +#endif /* CONFIG_ISDN_MPP */ for (i = 0; i < ISDN_MAX_CHANNELS; i++) { if (!(ippp_table[i] = (struct ippp_struct *) @@ -1108,6 +840,12 @@ for (i = 0; i < ISDN_MAX_CHANNELS; i++) kfree(ippp_table[i]); + +#ifdef CONFIG_ISDN_MPP + if (isdn_ppp_bundle_arr) + kfree(isdn_ppp_bundle_arr); +#endif /* CONFIG_ISDN_MPP */ + } /* @@ -1133,9 +871,16 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb) { struct ippp_struct *is; + int slot; int proto; - is = ippp_table[lp->ppp_slot]; + slot = lp->ppp_slot; + if (slot < 0 || slot > ISDN_MAX_CHANNELS) { + printk(KERN_ERR "isdn_ppp_receive: lp->ppp_slot %d\n", lp->ppp_slot); + kfree_skb(skb); + return; + } + is = ippp_table[slot]; if (is->debug & 0x4) { printk(KERN_DEBUG "ippp_receive: is:%08lx lp:%08lx slot:%d unit:%d len:%d\n", @@ -1157,7 +902,6 @@ #ifdef CONFIG_ISDN_MPP if (!(is->mpppcfg & SC_REJ_MP_PROT)) { - int sqno_end; if(is->compflags & SC_LINK_DECOMP_ON) { if(proto == PPP_COMPFRAG) { @@ -1173,150 +917,12 @@ } if (proto == PPP_MP) { - isdn_net_local *lpq; - long sqno, min_sqno, tseq; - - u_char BEbyte = skb->data[0]; - if (is->debug & 0x8) - printk(KERN_DEBUG "recv: %d/%04x/%d -> %02x %02x %02x %02x %02x %02x\n", lp->ppp_slot, proto, - (int) skb->len, (int) skb->data[0], (int) skb->data[1], (int) skb->data[2], - (int) skb->data[3], (int) skb->data[4], (int) skb->data[5]); - if (!(is->mpppcfg & SC_IN_SHORT_SEQ)) { - sqno = ((int) skb->data[1] << 16) + ((int) skb->data[2] << 8) + (int) skb->data[3]; - skb_pull(skb, 4); - } else { - sqno = (((int) skb->data[0] & 0xf) << 8) + (int) skb->data[1]; - skb_pull(skb, 2); - } - - /* - * new sequence number lower than last number? (this is only allowed - * for overflow case) - */ - if ((tseq = is->last_link_seqno) >= sqno) { - int range = is->range; - if (tseq + 1024 < range + sqno) /* redundancy check .. not MP conform */ - printk(KERN_WARNING "isdn_ppp_receive, MP, detected overflow with sqno: %ld, last: %ld !!!\n", sqno, tseq); - else { - sqno += range; - is->last_link_seqno = sqno; - } - } else { - /* here, we should also add an redundancy check */ - is->last_link_seqno = sqno; - } - - /* - * step over all links to find lowest link number - */ - for (min_sqno = LONG_MAX, lpq = net_dev->queue;;) { - long lls = ippp_table[lpq->ppp_slot]->last_link_seqno; - if (lls >= 0 && lls < min_sqno) - min_sqno = lls; - lpq = lpq->next; - if (lpq == net_dev->queue) - break; - } - - /* - * for the case, that the last frame numbers of all - * links are overflowed: mask/reduce the sequenece number to - * 'normal' numbering. - */ - if (min_sqno >= ippp_table[lpq->ppp_slot]->range) { - int mask = ippp_table[lpq->ppp_slot]->range-1; /* range is power of two, so a mask will do the job */ - isdn_ppp_mask_queue(net_dev, mask); - net_dev->ib.next_num &= mask; - { - struct sqqueue *q = net_dev->ib.sq; - while (q) { - q->sqno_start &= mask; - q->sqno_end &= mask; - } - } - min_sqno &= mask; - for (lpq = net_dev->queue;;) { - if(ippp_table[lpq->ppp_slot]->last_link_seqno >= 0) - ippp_table[lpq->ppp_slot]->last_link_seqno &= mask; - lpq = lpq->next; - if (lpq == net_dev->queue) - break; - } - } - if ((BEbyte & (MP_BEGIN_FRAG | MP_END_FRAG)) != (MP_BEGIN_FRAG | MP_END_FRAG)) { - static int dmes = 0; - if( !dmes ) { - printk(KERN_DEBUG "ippp: trying ;) to fill mp_queue %d .. UNTESTED!!\n", lp->ppp_slot); - dmes = 1; - } - if ((sqno_end = isdn_ppp_fill_mpqueue(net_dev, &skb, BEbyte, &sqno, min_sqno)) < 0) { - net_dev->ib.modify = 1; /* block timeout-timer */ - isdn_ppp_cleanup_sqqueue(net_dev, lp, min_sqno); - net_dev->ib.modify = 0; - return; /* no packet complete */ - } - } else - sqno_end = sqno; - - if (is->debug & 0x40) - printk(KERN_DEBUG "min_sqno: %ld sqno_end %d next: %ld\n", min_sqno, sqno_end, net_dev->ib.next_num); - - /* - * MP buffer management .. reorders incoming packets .. - * lotsa mem-copies and not heavily tested. - * - * first check whether there is more than one link in the bundle - * then check whether the number is in order - */ - net_dev->ib.modify = 1; /* block timeout-timer */ - if (net_dev->ib.bundled && net_dev->ib.next_num != sqno) { - /* - * packet is not 'in order' - */ - struct sqqueue *q; - - q = (struct sqqueue *) kmalloc(sizeof(struct sqqueue), GFP_ATOMIC); - if (!q) { - net_dev->ib.modify = 0; - printk(KERN_WARNING "ippp/MPPP: Bad! Can't alloc sq node!\n"); - dev_kfree_skb(skb); - return; /* discard */ - } - q->skb = skb; - q->sqno_end = sqno_end; - q->sqno_start = sqno; - q->timer = jiffies + (ISDN_TIMER_1SEC) * 5; /* timeout after 5 seconds */ - - if (!net_dev->ib.sq) { - net_dev->ib.sq = q; - q->next = NULL; - } else { - struct sqqueue *ql = net_dev->ib.sq; - if (ql->sqno_start > q->sqno_start) { - q->next = ql; - net_dev->ib.sq = q; - } else { - while (ql->next && ql->next->sqno_start < q->sqno_start) - ql = ql->next; - q->next = ql->next; - ql->next = q; - } - } - } else { - /* - * packet was 'in order' .. push it higher - */ - net_dev->ib.next_num = sqno_end + 1; - proto = isdn_ppp_strip_proto(skb); - isdn_ppp_push_higher(net_dev, lp, skb, proto); - } - isdn_ppp_cleanup_sqqueue(net_dev, lp, min_sqno); - net_dev->ib.modify = 0; - - } else + isdn_ppp_mp_receive(net_dev, lp, skb); + } + else isdn_ppp_push_higher(net_dev, lp, skb, proto); } else -#endif +#endif /* CONFIG_ISDN_MPP */ isdn_ppp_push_higher(net_dev, lp, skb, proto); } @@ -1328,8 +934,16 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb, int proto) { struct net_device *dev = &net_dev->dev; - struct ippp_struct *is = ippp_table[lp->ppp_slot]; + struct ippp_struct *is; + int slot; + slot = lp->ppp_slot; + if (slot < 0 || slot > ISDN_MAX_CHANNELS) { + printk(KERN_ERR "isdn_ppp_push_higher: lp->ppp_slot %d\n", lp->ppp_slot); + kfree_skb(skb); + return; + } + is = ippp_table[slot]; if (is->debug & 0x10) { printk(KERN_DEBUG "push, skb %d %04x\n", (int) skb->len, proto); isdn_ppp_frame_log("rpush", skb->data, skb->len, 32,is->unit,lp->ppp_slot); @@ -1486,11 +1100,18 @@ isdn_net_dev *nd; unsigned int proto = PPP_IP; /* 0x21 */ struct ippp_struct *ipt,*ipts; + int slot; mlp = (isdn_net_local *) (netdev->priv); - nd = mlp->netdev; /* get master lp */ - ipts = ippp_table[mlp->ppp_slot]; + + slot = mlp->ppp_slot; + if (slot < 0 || slot > ISDN_MAX_CHANNELS) { + printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot %d\n", mlp->ppp_slot); + kfree_skb(skb); + return 0; + } + ipts = ippp_table[slot]; if (!(ipts->pppcfg & SC_ENABLE_IP)) { /* PPP connected ? */ if (ipts->debug & 0x1) @@ -1514,12 +1135,18 @@ lp = isdn_net_get_locked_lp(nd); if (!lp) { - printk(KERN_WARNING "%s: all channels busy - requeuing!\n", lp->name); + printk(KERN_WARNING "%s: all channels busy - requeuing!\n", netdev->name); return 1; } /* we have our lp locked from now on */ - ipt = ippp_table[lp->ppp_slot]; + slot = lp->ppp_slot; + if (slot < 0 || slot > ISDN_MAX_CHANNELS) { + printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot %d\n", lp->ppp_slot); + kfree_skb(skb); + return 0; + } + ipt = ippp_table[slot]; lp->huptimer = 0; /* @@ -1666,351 +1293,466 @@ #ifdef CONFIG_ISDN_MPP -/* - * free SQ queue - * ------------- - * Note: We need two queues for MPPP. The SQ queue holds fully (re)assembled frames, - * that can't be delivered, because there is an outstanding earlier frame - */ -static void -isdn_ppp_free_sqqueue(isdn_net_dev * p) -{ - struct sqqueue *q = p->ib.sq; +/* this is _not_ rfc1990 header, but something we convert both short and long + * headers to for convinience's sake: + * byte 0 is flags as in rfc1990 + * bytes 1...4 is 24-bit seqence number converted to host byte order + */ +#define MP_HEADER_LEN 5 + +#define MP_LONGSEQ_MASK 0x00ffffff +#define MP_SHORTSEQ_MASK 0x00000fff +#define MP_LONGSEQ_MAX MP_LONGSEQ_MASK +#define MP_SHORTSEQ_MAX MP_SHORTSEQ_MASK +#define MP_LONGSEQ_MAXBIT ((MP_LONGSEQ_MASK+1)>>1) +#define MP_SHORTSEQ_MAXBIT ((MP_SHORTSEQ_MASK+1)>>1) + +/* sequence-wrap safe comparisions (for long sequence)*/ +#define MP_LT(a,b) ((a-b)&MP_LONGSEQ_MAXBIT) +#define MP_LE(a,b) !((b-a)&MP_LONGSEQ_MAXBIT) +#define MP_GT(a,b) ((b-a)&MP_LONGSEQ_MAXBIT) +#define MP_GE(a,b) !((a-b)&MP_LONGSEQ_MAXBIT) - p->ib.sq = NULL; - while (q) { - struct sqqueue *qn = q->next; - if (q->skb) - dev_kfree_skb(q->skb); - kfree(q); - q = qn; - } +#define MP_SEQ(f) ((*(u32*)(f->data+1))) +#define MP_FLAGS(f) (f->data[0]) +static int isdn_ppp_mp_bundle_array_init(void) +{ + int i; + int sz = ISDN_MAX_CHANNELS*sizeof(ippp_bundle); + if( (isdn_ppp_bundle_arr = (ippp_bundle*)kmalloc(sz, + GFP_KERNEL)) == NULL ) + return -ENOMEM; + memset(isdn_ppp_bundle_arr, 0, sz); + for( i = 0; i < ISDN_MAX_CHANNELS; i++ ) + spin_lock_init(&isdn_ppp_bundle_arr[i].lock); + return 0; } -/* - * free MP queue - * ------------- - * Note: The MP queue holds all frame fragments of frames, that can't be - * reassembled, because there is at least one missing fragment. - */ -static void -isdn_ppp_free_mpqueue(isdn_net_dev * p) -{ - struct mpqueue *q = p->mp_last; - p->mp_last = NULL; - - while (q) { - struct mpqueue *ql = q->next; - dev_kfree_skb(q->skb); - kfree(q); - q = ql; +static ippp_bundle * isdn_ppp_mp_bundle_alloc(void) +{ + int i; + for( i = 0; i < ISDN_MAX_CHANNELS; i++ ) + if (isdn_ppp_bundle_arr[i].ref_ct <= 0) + return (isdn_ppp_bundle_arr + i); + return NULL; +} + +static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to ) +{ + struct ippp_struct * is = ippp_table[lp->ppp_slot]; + + if (add_to) { + if( lp->netdev->pb ) + lp->netdev->pb->ref_ct--; + lp->netdev->pb = add_to; + } else { /* first link in a bundle */ + is->mp_seqno = 0; + if ((lp->netdev->pb = isdn_ppp_mp_bundle_alloc()) == NULL) + return -ENOMEM; + lp->next = lp->last = lp; /* nobody else in a queue */ + lp->netdev->pb->frags = NULL; + lp->netdev->pb->frames = 0; + lp->netdev->pb->seq = LONG_MAX; } + lp->netdev->pb->ref_ct++; + + is->last_link_seqno = 0; + return 0; } -static int -isdn_ppp_bundle(struct ippp_struct *is, int unit) +static u32 isdn_ppp_mp_get_seq( int short_seq, + struct sk_buff * skb, u32 last_seq ); +struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp, + struct sk_buff * from, struct sk_buff * to ); +void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp, + struct sk_buff * from, struct sk_buff * to ); +static void isdn_ppp_mp_free_skb( ippp_bundle * mp, struct sk_buff * skb ); +static void isdn_ppp_mp_print_recv_pkt( int slot, struct sk_buff * skb ); + +static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, + struct sk_buff *skb) { - char ifn[IFNAMSIZ + 1]; - long flags; - isdn_net_dev *p; - isdn_net_local *lp, *nlp; + struct ippp_struct *is; + isdn_net_local * lpq; + ippp_bundle * mp; + isdn_mppp_stats * stats; + struct sk_buff * newfrag, * frag, * start, *nextf; + u32 newseq, minseq, thisseq; + unsigned long flags; + int slot; - sprintf(ifn, "ippp%d", unit); - p = isdn_net_findif(ifn); - if (!p) - return -1; + spin_lock_irqsave(&net_dev->pb->lock, flags); + mp = net_dev->pb; + stats = &mp->stats; + slot = lp->ppp_slot; + if (slot < 0 || slot > ISDN_MAX_CHANNELS) { + printk(KERN_ERR "isdn_ppp_mp_receive: lp->ppp_slot %d\n", lp->ppp_slot); + stats->frame_drops++; + dev_kfree_skb(skb); + spin_unlock_irqrestore(&mp->lock, flags); + return; + } + is = ippp_table[slot]; + if( ++mp->frames > stats->max_queue_len ) + stats->max_queue_len = mp->frames; + + if (is->debug & 0x8) + isdn_ppp_mp_print_recv_pkt(lp->ppp_slot, skb); - save_flags(flags); - cli(); - isdn_timer_ctrl(ISDN_TIMER_IPPP, 1); /* enable timer for ippp/MP */ + newseq = isdn_ppp_mp_get_seq(is->mpppcfg & SC_IN_SHORT_SEQ, + skb, is->last_link_seqno); - nlp = is->lp; - lp = p->queue; - isdn_net_add_to_bundle(p, nlp); - p->ib.bundled = 1; - ippp_table[nlp->ppp_slot]->unit = ippp_table[lp->ppp_slot]->unit; -/* maybe also SC_CCP stuff */ - ippp_table[nlp->ppp_slot]->pppcfg |= ippp_table[lp->ppp_slot]->pppcfg & - (SC_ENABLE_IP | SC_NO_TCP_CCID | SC_REJ_COMP_TCP); - - ippp_table[nlp->ppp_slot]->mpppcfg |= ippp_table[lp->ppp_slot]->mpppcfg & - (SC_MP_PROT | SC_REJ_MP_PROT | SC_OUT_SHORT_SEQ | SC_IN_SHORT_SEQ); - restore_flags(flags); - return 0; -} - -/* - * Mask sequence numbers in MP queue - */ -static void -isdn_ppp_mask_queue(isdn_net_dev * dev, long mask) -{ - struct mpqueue *q = dev->mp_last; - while (q) { - q->sqno &= mask; - q = q->next; + /* if this packet seq # is less than last already processed one, + * toss it right away, but check for sequence start case first + */ + if( mp->seq > MP_LONGSEQ_MAX && (newseq & MP_LONGSEQ_MAXBIT) ) { + mp->seq = newseq; /* the first packet: required for + * rfc1990 non-compliant clients -- + * prevents constant packet toss */ + } else if( MP_LT(newseq, mp->seq) ) { + stats->frame_drops++; + isdn_ppp_mp_free_skb(mp, skb); + spin_unlock_irqrestore(&mp->lock, flags); + return; } -} - -/* - * put a fragment at the right place into the MP queue - * Also checks, whether this fragment completes a frame. In this case - * the fragments are copied together into one SKB - */ -static int -isdn_ppp_fill_mpqueue(isdn_net_dev * dev, struct sk_buff **skb, int BEbyte, long *sqnop, int min_sqno) -{ - struct mpqueue *qe, - *q1, - *q; - long cnt, - flags; - int pktlen, - sqno_end; - int sqno = *sqnop; - - q1 = (struct mpqueue *) kmalloc(sizeof(struct mpqueue), GFP_ATOMIC); - if (!q1) { - printk(KERN_WARNING "isdn_ppp_fill_mpqueue: Can't alloc struct memory.\n"); - save_flags(flags); - cli(); - isdn_ppp_cleanup_mpqueue(dev, min_sqno); - restore_flags(flags); - return -1; + + /* find the minimum received sequence number over all links */ + is->last_link_seqno = minseq = newseq; + for (lpq = net_dev->queue;;) { + slot = lpq->ppp_slot; + if (slot < 0 || slot > ISDN_MAX_CHANNELS) { + printk(KERN_ERR "isdn_ppp_mp_receive: lpq->ppp_slot %d\n", lpq->ppp_slot); + } else { + u32 lls = ippp_table[slot]->last_link_seqno; + if (MP_LT(lls, minseq)) + minseq = lls; + } + if ((lpq = lpq->next) == net_dev->queue) + break; } - q1->skb = *skb; - q1->sqno = sqno; - q1->BEbyte = BEbyte; - q1->time = jiffies; + if (MP_LT(minseq, mp->seq)) + minseq = mp->seq; /* can't go beyond already processed + * packets */ + newfrag = skb; + + /* if this new fragment is before the first one, then enqueue it now. */ + if ((frag = mp->frags) == NULL || MP_LT(newseq, MP_SEQ(frag))) { + newfrag->next = frag; + mp->frags = frag = newfrag; + newfrag = NULL; + } + + start = MP_FLAGS(frag) & MP_BEGIN_FRAG && + MP_SEQ(frag) == mp->seq ? frag : NULL; + + /* + * main fragment traversing loop + * + * try to accomplish several tasks: + * - insert new fragment into the proper sequence slot (once that's done + * newfrag will be set to NULL) + * - reassemble any complete fragment sequence (non-null 'start' + * indicates there is a continguous sequence present) + * - discard any incomplete sequences that are below minseq -- due + * to the fact that sender always increment sequence number, if there + * is an incomplete sequence below minseq, no new fragments would + * come to complete such sequence and it should be discarded + * + * loop completes when we accomplished the following tasks: + * - new fragment is inserted in the proper sequence ('newfrag' is + * set to NULL) + * - we hit a gap in the sequence, so no reassembly/processing is + * possible ('start' would be set to NULL) + * + * algorightm for this code is derived from code in the book + * 'PPP Design And Debugging' by James Carlson (Addison-Wesley) + */ + while (start != NULL || newfrag != NULL) { - save_flags(flags); - cli(); + thisseq = MP_SEQ(frag); + nextf = frag->next; - if (!(q = dev->mp_last)) { - dev->mp_last = q1; - q1->next = NULL; - q1->last = NULL; - isdn_ppp_cleanup_mpqueue(dev, min_sqno); /* not necessary */ - restore_flags(flags); - return -1; /* -1 is not an error. Just says, that this fragment hasn't complete a full frame */ - } - for (;;) { /* the faster way would be to step from the queue-end to the start */ - if (sqno > q->sqno) { - if (q->next) { - q = q->next; + /* drop any duplicate fragments */ + if (newfrag != NULL && thisseq == newseq) { + isdn_ppp_mp_free_skb(mp, newfrag); + newfrag = NULL; + } + + /* insert new fragment before next element if possible. */ + if (newfrag != NULL && (nextf == NULL || + MP_LT(newseq, MP_SEQ(nextf)))) { + newfrag->next = nextf; + frag->next = nextf = newfrag; + newfrag = NULL; + } + + if (start != NULL) { + /* check for misplaced start */ + if (start != frag && (MP_FLAGS(frag) & MP_BEGIN_FRAG)) { + printk(KERN_WARNING"isdn_mppp(seq %d): new " + "BEGIN flag with no prior END", thisseq); + stats->seqerrs++; + stats->frame_drops++; + start = isdn_ppp_mp_discard(mp, start,frag); + nextf = frag->next; + } + } else if (MP_LE(thisseq, minseq)) { + if (MP_FLAGS(frag) & MP_BEGIN_FRAG) + start = frag; + else { + if (MP_FLAGS(frag) & MP_END_FRAG) + stats->frame_drops++; + if( mp->frags == frag ) + mp->frags = nextf; + isdn_ppp_mp_free_skb(mp, frag); + frag = nextf; continue; - } - q->next = q1; - q1->next = NULL; - q1->last = q; - break; + } } - if (sqno == q->sqno) - printk(KERN_WARNING "isdn_fill_mpqueue: illegal sqno received!!\n"); - q1->last = q->last; - q1->next = q; - if (q->last) { - q->last->next = q1; - } else - dev->mp_last = q1; - q->last = q1; - break; - } - -/* now we check whether we completed a packet with this fragment */ - pktlen = -q1->skb->len; - q = q1; - cnt = q1->sqno; - while (!(q->BEbyte & MP_END_FRAG)) { - cnt++; - if (!(q->next) || q->next->sqno != cnt) { - isdn_ppp_cleanup_mpqueue(dev, min_sqno); - restore_flags(flags); - return -1; + + /* if start is non-null and we have end fragment, then + * we have full reassembly sequence -- reassemble + * and process packet now + */ + if (start != NULL && (MP_FLAGS(frag) & MP_END_FRAG)) { + minseq = mp->seq = (thisseq+1) & MP_LONGSEQ_MASK; + /* Reassemble the packet then dispatch it */ + isdn_ppp_mp_reassembly(net_dev, lp, start, nextf); + + start = NULL; + frag = NULL; + + mp->frags = nextf; + } + + /* check if need to update start pointer: if we just + * reassembled the packet and sequence is contiguous + * then next fragment should be the start of new reassembly + * if sequence is contiguous, but we haven't reassembled yet, + * keep going. + * if sequence is not contiguous, either clear everyting + * below low watermark and set start to the next frag or + * clear start ptr. + */ + if (nextf != NULL && + ((thisseq+1) & MP_LONGSEQ_MASK) == MP_SEQ(nextf)) { + /* if we just reassembled and the next one is here, + * then start another reassembly. */ + + if (frag == NULL) { + if (MP_FLAGS(nextf) & MP_BEGIN_FRAG) + start = nextf; + else + { + printk(KERN_WARNING"isdn_mppp(seq %d):" + " END flag with no following " + "BEGIN", thisseq); + stats->seqerrs++; + } + } + + } else { + if ( nextf != NULL && frag != NULL && + MP_LT(thisseq, minseq)) { + /* we've got a break in the sequence + * and we not at the end yet + * and we did not just reassembled + *(if we did, there wouldn't be anything before) + * and we below the low watermark + * discard all the frames below low watermark + * and start over */ + stats->frame_drops++; + mp->frags = isdn_ppp_mp_discard(mp,start,nextf); + } + /* break in the sequence, no reassembly */ + start = NULL; + } + + frag = nextf; + } /* while -- main loop */ + + if (mp->frags == NULL) + mp->frags = frag; + + /* rather straighforward way to deal with (not very) possible + * queue overflow */ + if (mp->frames > MP_MAX_QUEUE_LEN) { + stats->overflows++; + while (mp->frames > MP_MAX_QUEUE_LEN) { + frag = mp->frags->next; + isdn_ppp_mp_free_skb(mp, mp->frags); + mp->frags = frag; } - pktlen += q->skb->len; - q = q->next; } - pktlen += q->skb->len; - qe = q; + spin_unlock_irqrestore(&mp->lock, flags); +} - q = q1; - cnt = q1->sqno; - while (!(q->BEbyte & MP_BEGIN_FRAG)) { - cnt--; - if (!(q->last) || q->last->sqno != cnt) { - isdn_ppp_cleanup_mpqueue(dev, min_sqno); - restore_flags(flags); - return -1; - } - pktlen += q->skb->len; - q = q->last; +static void isdn_ppp_mp_cleanup( isdn_net_local * lp ) +{ + struct sk_buff * frag = lp->netdev->pb->frags; + struct sk_buff * nextfrag; + while( frag ) { + nextfrag = frag->next; + isdn_ppp_mp_free_skb(lp->netdev->pb, frag); + frag = nextfrag; } - pktlen += q->skb->len; + lp->netdev->pb->frags = NULL; +} - if (q->last) - q->last->next = qe->next; +static u32 isdn_ppp_mp_get_seq( int short_seq, + struct sk_buff * skb, u32 last_seq ) +{ + u32 seq; + int flags = skb->data[0] & (MP_BEGIN_FRAG | MP_END_FRAG); + + if( !short_seq ) + { + seq = ntohl(*(u32*)skb->data) & MP_LONGSEQ_MASK; + skb_push(skb,1); + } else - dev->mp_last = qe->next; + { + /* convert 12-bit short seq number to 24-bit long one + */ + seq = ntohs(*(u16*)skb->data) & MP_SHORTSEQ_MASK; + + /* check for seqence wrap */ + if( !(seq & MP_SHORTSEQ_MAXBIT) && + (last_seq & MP_SHORTSEQ_MAXBIT) && + (unsigned long)last_seq <= MP_LONGSEQ_MAX ) + seq |= (last_seq + MP_SHORTSEQ_MAX+1) & + (~MP_SHORTSEQ_MASK & MP_LONGSEQ_MASK); + else + seq |= last_seq & (~MP_SHORTSEQ_MASK & MP_LONGSEQ_MASK); + + skb_push(skb, 3); /* put converted seqence back in skb */ + } + *(u32*)(skb->data+1) = seq; /* put seqence back in _host_ byte + * order */ + skb->data[0] = flags; /* restore flags */ + return seq; +} + +struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp, + struct sk_buff * from, struct sk_buff * to ) +{ + if( from ) + while (from != to) { + struct sk_buff * next = from->next; + isdn_ppp_mp_free_skb(mp, from); + from = next; + } + return from; +} - if (qe->next) - qe->next->last = q->last; - qe->next = NULL; - sqno_end = qe->sqno; - *sqnop = q->sqno; +void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp, + struct sk_buff * from, struct sk_buff * to ) +{ + ippp_bundle * mp = net_dev->pb; + int proto; + struct sk_buff * skb; + unsigned int tot_len; - isdn_ppp_cleanup_mpqueue(dev, min_sqno); - restore_flags(flags); + if( MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG) ) { + if( ippp_table[lp->ppp_slot]->debug & 0x40 ) + printk(KERN_DEBUG"isdn_mppp: reassembly: frame %d, " + "len %d\n", MP_SEQ(from), from->len ); + skb = from; + skb_pull(skb, MP_HEADER_LEN); + mp->frames--; + } else { + struct sk_buff * frag; + int n; - *skb = dev_alloc_skb(pktlen + 40); /* not needed: +40 for VJ compression .. */ + for(tot_len=n=0, frag=from; frag != to; frag=frag->next, n++) + tot_len += frag->len - MP_HEADER_LEN; - if (!(*skb)) { - while (q) { - struct mpqueue *ql = q->next; - dev_kfree_skb(q->skb); - kfree(q); - q = ql; + if( ippp_table[lp->ppp_slot]->debug & 0x40 ) + printk(KERN_DEBUG"isdn_mppp: reassembling frames %d " + "to %d, len %d\n", MP_SEQ(from), + (MP_SEQ(from)+n-1) & MP_LONGSEQ_MASK, tot_len ); + if( (skb = dev_alloc_skb(tot_len)) == NULL ) { + printk(KERN_ERR "isdn_mppp: cannot allocate sk buff " + "of size %d\n", tot_len); + isdn_ppp_mp_discard(mp, from, to); + return; } - return -2; - } - cnt = 0; - skb_put(*skb, pktlen); - while (q) { - struct mpqueue *ql = q->next; - memcpy((*skb)->data + cnt, q->skb->data, q->skb->len); - cnt += q->skb->len; - dev_kfree_skb(q->skb); - kfree(q); - q = ql; - } - return sqno_end; -} + while( from != to ) { + unsigned int len = from->len - MP_HEADER_LEN; -/* - * check sq-queue, whether we have still buffered the next packet(s) - * or packets with a sqno less or equal to min_sqno - * net_dev: master netdevice , lp: 'real' local connection - */ -static void -isdn_ppp_cleanup_sqqueue(isdn_net_dev * net_dev, isdn_net_local * lp, long min_sqno) -{ - struct sqqueue *q; - - while ((q = net_dev->ib.sq) && (q->sqno_start == net_dev->ib.next_num || q->sqno_end <= min_sqno)) { - int proto; - if (q->sqno_start != net_dev->ib.next_num) { - printk(KERN_DEBUG "ippp: MP, stepping over missing frame: %ld\n", net_dev->ib.next_num); -#ifdef CONFIG_ISDN_PPP_VJ - slhc_toss(ippp_table[net_dev->local->ppp_slot]->slcomp); -#endif + memcpy(skb_put(skb,len), from->data+MP_HEADER_LEN, len); + frag = from->next; + isdn_ppp_mp_free_skb(mp, from); + from = frag; } - proto = isdn_ppp_strip_proto(q->skb); - isdn_ppp_push_higher(net_dev, lp, q->skb, proto); - net_dev->ib.sq = q->next; - net_dev->ib.next_num = q->sqno_end + 1; - kfree(q); } + proto = isdn_ppp_strip_proto(skb); + isdn_ppp_push_higher(net_dev, lp, skb, proto); } -/* - * remove stale packets from list - */ -static void -isdn_ppp_cleanup_mpqueue(isdn_net_dev * dev, long min_sqno) +static void isdn_ppp_mp_free_skb(ippp_bundle * mp, struct sk_buff * skb) { -#ifdef CONFIG_ISDN_PPP_VJ - int toss = 0; -#endif - /* currently we just discard ancient packets. - To do: - Maybe, as long as there's no B-packet in front and sqno <= min_sqno: discard. - If sqno < min_sqno and there are gaps: discard (the gaps won't be filled anyway). - Packets with sqno > min_sqno: Larger than mp_mrru: If sum of all pktlen of pending - packets large than mrru: discard - packets need to be consecutive, though, if not - there could be an B and an E-packet in between. - */ - - struct mpqueue *ql, - *q = dev->mp_last; - while(q && (q->sqno < min_sqno) ) { - if ( (q->BEbyte & MP_END_FRAG) || - (q->next && (q->next->sqno <= min_sqno) && (q->next->BEbyte & MP_BEGIN_FRAG)) ) { - printk(KERN_DEBUG "ippp: freeing stale packet(s), min_sq: %ld!\n",min_sqno); - if ((dev->mp_last = q->next)) - q->next->last = NULL; - while (q) { - ql = q->last; - printk(KERN_DEBUG "ippp, freeing packet with sqno: %ld\n",q->sqno); - dev_kfree_skb(q->skb); - kfree(q); -#ifdef CONFIG_ISDN_PPP_VJ - toss = 1; -#endif - q = ql; - } - q = dev->mp_last; - } else - q = q->next; - } -#ifdef CONFIG_ISDN_PPP_VJ - /* did we free a stale frame ? */ - if (toss) - slhc_toss(ippp_table[dev->local->ppp_slot]->slcomp); -#endif + dev_kfree_skb(skb); + mp->frames--; } -#endif -/* - * a buffered packet timed-out? - */ -void -isdn_ppp_timer_timeout(void) +static void isdn_ppp_mp_print_recv_pkt( int slot, struct sk_buff * skb ) { -#ifdef CONFIG_ISDN_MPP - isdn_net_dev *net_dev = dev->netdev; - struct sqqueue *q, - *ql = NULL, - *qn; - - while (net_dev) { - isdn_net_local *lp = net_dev->local; - if (net_dev->ib.modify || lp->master) { /* interface locked or slave? */ - net_dev = net_dev->next; - continue; - } - q = net_dev->ib.sq; - while (q) { - if (q->sqno_start == net_dev->ib.next_num || q->timer < jiffies) { + printk(KERN_DEBUG "mp_recv: %d/%d -> %02x %02x %02x %02x %02x %02x\n", + slot, (int) skb->len, + (int) skb->data[0], (int) skb->data[1], (int) skb->data[2], + (int) skb->data[3], (int) skb->data[4], (int) skb->data[5]); +} -#ifdef CONFIG_ISDN_PPP_VJ - /* did we step over a missing frame ? */ - if (q->sqno_start != net_dev->ib.next_num) - slhc_toss(ippp_table[lp->ppp_slot]->slcomp); -#endif +static int +isdn_ppp_bundle(struct ippp_struct *is, int unit) +{ + char ifn[IFNAMSIZ + 1]; + isdn_net_dev *p; + isdn_net_local *lp, *nlp; + int rc; + unsigned long flags; - ql = net_dev->ib.sq; - net_dev->ib.sq = q->next; - net_dev->ib.next_num = q->sqno_end + 1; - q->next = NULL; - for (; ql;) { - int proto = isdn_ppp_strip_proto(ql->skb); - isdn_ppp_push_higher(net_dev, lp, ql->skb, proto); - qn = ql->next; - kfree(ql); - ql = qn; - } - q = net_dev->ib.sq; - } else - q = q->next; - } - net_dev = net_dev->next; + sprintf(ifn, "ippp%d", unit); + p = isdn_net_findif(ifn); + if (!p) { + printk(KERN_ERR "ippp_bundle: cannot find %s\n", ifn); + return -EINVAL; } -#endif -} + spin_lock_irqsave(&p->pb->lock, flags); + + nlp = is->lp; + lp = p->queue; + if( nlp->ppp_slot < 0 || nlp->ppp_slot >= ISDN_MAX_CHANNELS || + lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS ) { + printk(KERN_ERR "ippp_bundle: binding to invalid slot %d\n", + nlp->ppp_slot < 0 || nlp->ppp_slot >= ISDN_MAX_CHANNELS ? + nlp->ppp_slot : lp->ppp_slot ); + rc = -EINVAL; + goto out; + } + + isdn_net_add_to_bundle(p, nlp); + + ippp_table[nlp->ppp_slot]->unit = ippp_table[lp->ppp_slot]->unit; + + /* maybe also SC_CCP stuff */ + ippp_table[nlp->ppp_slot]->pppcfg |= ippp_table[lp->ppp_slot]->pppcfg & + (SC_ENABLE_IP | SC_NO_TCP_CCID | SC_REJ_COMP_TCP); + ippp_table[nlp->ppp_slot]->mpppcfg |= ippp_table[lp->ppp_slot]->mpppcfg & + (SC_MP_PROT | SC_REJ_MP_PROT | SC_OUT_SHORT_SEQ | SC_IN_SHORT_SEQ); + rc = isdn_ppp_mp_init(nlp, p->pb); +out: + spin_unlock_irqrestore(&p->pb->lock, flags); + return rc; +} + +#endif /* CONFIG_ISDN_MPP */ + /* * network device ioctl handlers */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/isdn_ppp.h linux/drivers/isdn/isdn_ppp.h --- v2.4.0-test5/linux/drivers/isdn/isdn_ppp.h Mon Jul 10 16:47:23 2000 +++ linux/drivers/isdn/isdn_ppp.h Tue Aug 8 15:03:57 2000 @@ -1,4 +1,4 @@ -/* $Id: isdn_ppp.h,v 1.14 1999/08/22 20:26:10 calle Exp $ +/* $Id: isdn_ppp.h,v 1.16 2000/05/18 23:14:18 keil Exp $ * header for Linux ISDN subsystem, functions for synchronous PPP (linklevel). * @@ -18,66 +18,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Log: isdn_ppp.h,v $ - * Revision 1.14 1999/08/22 20:26:10 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.13 1998/03/22 18:50:50 hipp - * Added BSD Compression for syncPPP .. UNTESTED at the moment - * - * Revision 1.12 1998/01/31 22:07:48 keil - * changes for newer kernels - * - * Revision 1.11 1997/10/01 09:20:44 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.10 1997/06/17 13:06:00 hipp - * Applied Eric's underflow-patches (slightly modified) - * more compression changes (but disabled at the moment) - * changed one copy_to_user() to run with enabled IRQs - * a few MP changes - * changed 'proto' handling in the isdn_ppp receive code - * - * Revision 1.9 1997/02/11 18:32:59 fritz - * Bugfix in isdn_ppp_free_mpqueue(). - * - * Revision 1.8 1997/02/10 10:11:33 fritz - * More changes for Kernel 2.1.X compatibility. - * - * Revision 1.7 1997/02/03 23:18:57 fritz - * Removed isdn_ppp_free_sqqueue prototype - * and ippp_table (both static in isdn_ppp.c). - * - * Revision 1.6 1996/09/23 01:58:11 fritz - * Fix: With syncPPP encapsulation, discard LCP packets - * when calculating hangup timeout. - * - * Revision 1.5 1996/09/07 12:51:34 hipp - * *** empty log message *** - * - * Revision 1.4 1996/05/06 11:34:56 hipp - * fixed a few bugs - * - * Revision 1.3 1996/04/30 09:33:10 fritz - * Removed compatibility-macros. - * - * Revision 1.2 1996/04/20 16:35:11 fritz - * Changed isdn_ppp_receive to use sk_buff as parameter. - * Added definition of isdn_ppp_dial_slave and ippp_table. - * - * Revision 1.1 1996/01/10 21:39:10 fritz - * Initial revision - * */ #include /* for PPP_PROTOCOL */ #include /* for isdn_ppp info */ -extern void isdn_ppp_timer_timeout(void); extern int isdn_ppp_read(int, struct file *, char *, int); extern int isdn_ppp_write(int, struct file *, const char *, int); extern int isdn_ppp_open(int, struct file *); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/isdn_tty.c linux/drivers/isdn/isdn_tty.c --- v2.4.0-test5/linux/drivers/isdn/isdn_tty.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/isdn/isdn_tty.c Tue Aug 8 15:03:57 2000 @@ -1,4 +1,4 @@ -/* $Id: isdn_tty.c,v 1.84 2000/02/16 15:10:14 paul Exp $ +/* $Id: isdn_tty.c,v 1.93 2000/08/05 09:58:26 armin Exp $ * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel). * @@ -19,334 +19,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Log: isdn_tty.c,v $ - * Revision 1.84 2000/02/16 15:10:14 paul - * If a ttyI has no open FDs, don't connect incoming calls to it. - * (Hangup on close of last FD is still to be done.) - * - * Revision 1.83 2000/02/16 14:59:33 paul - * translated ISDN_MODEM_ANZREG to ISDN_MODEM_NUMREG for english speakers; - * used defines for result codes; - * fixed RING ... RUNG problem (no empty lines in between). - * - * Revision 1.82 2000/01/23 18:45:37 keil - * Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN) - * - * Revision 1.81 2000/01/20 19:55:33 keil - * Add FAX Class 1 support - * - * Revision 1.80 1999/11/07 13:34:30 armin - * Fixed AT command line editor - * - * Revision 1.79 1999/10/29 18:35:08 armin - * Check number len in isdn_get_msnstr() to avoid buffer overflow. - * - * Revision 1.78 1999/10/28 23:03:51 armin - * Bugfix: now freeing channel on modem_hup() even when - * usage on ttyI has changed and error-report for - * AT-commands on wrong channel-state. - * - * Revision 1.77 1999/10/26 21:13:14 armin - * using define for checking phone number len in isdn_tty_getdial() - * - * Revision 1.76 1999/10/11 22:16:26 keil - * Suspend/Resume is possible without explicit ID too - * - * Revision 1.75 1999/10/08 18:59:32 armin - * Bugfix of too small MSN buffer and checking phone number - * in isdn_tty_getdial() - * - * Revision 1.74 1999/09/04 06:20:04 keil - * Changes from kernel set_current_state() - * - * Revision 1.73 1999/08/28 21:56:27 keil - * misplaced #endif caused ttyI crash in 2.3.X - * - * Revision 1.72 1999/07/31 12:59:45 armin - * Added tty fax capabilities. - * - * Revision 1.71 1999/07/27 10:34:34 armin - * Fixed last change. Did not compile with AUDIO support off. - * - * Revision 1.70 1999/07/25 16:17:58 keil - * Fix Suspend/Resume - * - * Revision 1.69 1999/07/25 12:56:15 armin - * isdn_tty_at_cout() now queues the message if online and - * data is in queue or flip buffer is full. - * needed for fax connections. - * - * Revision 1.68 1999/07/11 17:51:51 armin - * Bugfix, "-" was missing for AT&L settings. - * - * Revision 1.67 1999/07/11 17:14:12 armin - * Added new layer 2 and 3 protocols for Fax and DSP functions. - * Moved "Add CPN to RING message" to new register S23, - * "Display message" is now correct on register S13 bit 7. - * New audio command AT+VDD implemented (deactivate DTMF decoder and - * activate possible existing hardware/DSP decoder). - * Moved some tty defines to .h file. - * Made whitespace possible in AT command line. - * Some AT-emulator output bugfixes. - * First Fax G3 implementations. - * - * Revision 1.66 1999/07/07 10:13:46 detabc - * remove unused messages - * - * Revision 1.65 1999/07/04 21:01:59 werner - * Added support for keypad and display (ported from 2.0) - * - * Revision 1.64 1999/07/01 08:30:00 keil - * compatibility to 2.3 kernel - * - * Revision 1.63 1999/04/12 12:33:39 fritz - * Changes from 2.0 tree. - * - * Revision 1.62 1999/03/02 12:04:48 armin - * -added ISDN_STAT_ADDCH to increase supported channels after - * register_isdn(). - * -ttyI now goes on-hook on ATZ when B-Ch is connected. - * -added timer-function for register S7 (Wait for Carrier). - * -analog modem (ISDN_PROTO_L2_MODEM) implementations. - * -on L2_MODEM a string will be appended to the CONNECT-Message, - * which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN. - * -variable "dialing" used for ATA also, for interrupting call - * establishment and register S7. - * - * Revision 1.61 1999/01/27 22:53:11 he - * minor updates (spellings, jiffies wrap around in isdn_tty) - * - * Revision 1.60 1998/11/15 23:57:32 keil - * changes for 2.1.127 - * - * Revision 1.59 1998/08/20 13:50:15 keil - * More support for hybrid modem (not working yet) - * - * Revision 1.58 1998/07/26 18:48:45 armin - * Added silence detection in voice receive mode. - * - * Revision 1.57 1998/06/26 15:12:36 fritz - * Added handling of STAT_ICALL with incomplete CPN. - * Added AT&L for ttyI emulator. - * Added more locking stuff in tty_write. - * - * Revision 1.56 1998/06/18 23:31:51 fritz - * Replaced cli()/restore_flags() in isdn_tty_write() by locking. - * Removed direct-senddown feature in isdn_tty_write because it will - * never succeed with locking and is useless anyway. - * - * Revision 1.55 1998/06/17 19:50:55 he - * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay()) - * brute force fix to avoid Ugh's in isdn_tty_write() - * cleaned up some dead code - * - * - * - * Revision 1.52 1998/03/19 13:18:21 keil - * Start of a CAPI like interface for supplementary Service - * first service: SUSPEND - * - * - * Revision 1.49 1998/03/08 00:01:59 fritz - * Bugfix: Lowlevel module usage and channel usage were not - * reset on NO DCHANNEL. - * - * Revision 1.48 1998/03/07 12:28:15 tsbogend - * fixed kernel unaligned traps on Linux/Alpha - * - * Revision 1.47 1998/02/22 19:44:14 fritz - * Bugfixes and improvements regarding V.110, V.110 now running. - * - * Revision 1.46 1998/02/20 17:23:08 fritz - * Changes for recent kernels. - * Merged in contributions by Thomas Pfeiffer (V.110 T.70+ Extended FAX stuff) - * Added symbolic constants for Modem-Registers. - * - * Revision 1.45 1998/01/31 22:07:49 keil - * changes for newer kernels - * - * Revision 1.44 1998/01/31 19:30:02 calle - * Merged changes from and for 2.1.82, not tested only compiled ... - * - * Revision 1.43 1997/10/09 21:29:04 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * New L1 error status (not yet in use). - * Cleaned up obsolete structures. - * Implemented Cisco-SLARP. - * Changed local net-interface data to be dynamically allocated. - * Removed old 2.0 compatibility stuff. - * - * Revision 1.42 1997/10/01 09:20:49 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.41 1997/05/27 15:17:31 fritz - * Added changes for recent 2.1.x kernels: - * changed return type of isdn_close - * queue_task_* -> queue_task - * clear/set_bit -> test_and_... where apropriate. - * changed type of hard_header_cache parameter. - * - * Revision 1.40 1997/03/24 22:55:27 fritz - * Added debug code for status callbacks. - * - * Revision 1.39 1997/03/21 18:25:56 fritz - * Corrected CTS handling. - * - * Revision 1.38 1997/03/07 12:13:35 fritz - * Bugfix: Send audio in adpcm format was broken. - * Bugfix: CTS handling was wrong. - * - * Revision 1.37 1997/03/07 01:37:34 fritz - * Bugfix: Did not compile with CONFIG_ISDN_AUDIO disabled. - * Bugfix: isdn_tty_tint() did not handle lowlevel errors correctly. - * Bugfix: conversion was wrong when sending ulaw audio. - * Added proper ifdef's for CONFIG_ISDN_AUDIO - * - * Revision 1.36 1997/03/04 21:41:55 fritz - * Fix: Excessive stack usage of isdn_tty_senddown() - * and isdn_tty_end_vrx() could lead to problems. - * - * Revision 1.35 1997/03/02 19:05:52 fritz - * Bugfix: Avoid recursion. - * - * Revision 1.34 1997/03/02 14:29:22 fritz - * More ttyI related cleanup. - * - * Revision 1.33 1997/02/28 02:32:45 fritz - * Cleanup: Moved some tty related stuff from isdn_common.c - * to isdn_tty.c - * Bugfix: Bisync protocol did not behave like documented. - * - * Revision 1.32 1997/02/23 15:43:03 fritz - * Small change in handling of incoming calls - * documented in newest version of ttyI.4 - * - * Revision 1.31 1997/02/21 13:05:57 fritz - * Bugfix: Remote hangup did not set location-info on ttyI's - * - * Revision 1.30 1997/02/18 09:41:05 fritz - * Added support for bitwise access to modem registers (ATSx.y=n, ATSx.y?). - * Beautified output of AT&V. - * - * Revision 1.29 1997/02/16 12:11:51 fritz - * Added S13,Bit4 option. - * - * Revision 1.28 1997/02/10 22:07:08 fritz - * Added 2 modem registers for numbering plan and screening info. - * - * Revision 1.27 1997/02/10 21:31:14 fritz - * Changed setup-interface (incoming and outgoing). - * - * Revision 1.26 1997/02/10 20:12:48 fritz - * Changed interface for reporting incoming calls. - * - * Revision 1.25 1997/02/03 23:04:30 fritz - * Reformatted according CodingStyle. - * skb->free stuff replaced by macro. - * Finished full-duplex audio. - * - * Revision 1.24 1997/01/14 01:32:42 fritz - * Changed audio receive not to rely on skb->users and skb->lock. - * Added ATI2 and related variables. - * Started adding full-duplex audio capability. - * - * Revision 1.23 1996/10/22 23:14:02 fritz - * Changes for compatibility to 2.0.X and 2.1.X kernels. - * - * Revision 1.22 1996/10/19 18:56:43 fritz - * ATZ did not change the xmitbuf size. - * - * Revision 1.21 1996/06/24 17:40:28 fritz - * Bugfix: Did not compile without CONFIG_ISDN_AUDIO - * - * Revision 1.20 1996/06/15 14:59:39 fritz - * Fixed isdn_tty_tint() to handle partially sent - * sk_buffs. - * - * Revision 1.19 1996/06/12 15:53:56 fritz - * Bugfix: AT+VTX and AT+VRX could be executed without - * having a connection. - * Missing check for NULL tty in isdn_tty_flush_buffer(). - * - * Revision 1.18 1996/06/07 11:17:33 tsbogend - * added missing #ifdef CONFIG_ISDN_AUDIO to make compiling without - * audio support possible - * - * Revision 1.17 1996/06/06 14:55:47 fritz - * Changed to support DTMF decoding on audio playback also. - * Bugfix: Added check for invalid info->isdn_driver in - * isdn_tty_senddown(). - * Clear ncarrier flag on last close() of a tty. - * - * Revision 1.16 1996/06/05 02:24:12 fritz - * Added DTMF decoder for audio mode. - * - * Revision 1.15 1996/06/03 20:35:01 fritz - * Fixed typos. - * - * Revision 1.14 1996/06/03 20:12:19 fritz - * Fixed typos. - * Added call to write_wakeup via isdn_tty_flush_buffer() - * in isdn_tty_modem_hup(). - * - * Revision 1.13 1996/05/31 01:33:29 fritz - * Changed buffering due to bad performance with mgetty. - * Now sk_buff is delayed allocated in isdn_tty_senddown - * using xmit_buff like in standard serial driver. - * Fixed module locking. - * Added DLE-DC4 handling in voice mode. - * - * Revision 1.12 1996/05/19 01:34:40 fritz - * Bugfix: ATS returned error. - * Register 20 made readonly. - * - * Revision 1.11 1996/05/18 01:37:03 fritz - * Added spelling corrections and some minor changes - * to stay in sync with kernel. - * - * Revision 1.10 1996/05/17 03:51:49 fritz - * Changed DLE handling for audio receive. - * - * Revision 1.9 1996/05/11 21:52:07 fritz - * Changed queue management to use sk_buffs. - * - * Revision 1.8 1996/05/10 08:49:43 fritz - * Checkin before major changes of tty-code. - * - * Revision 1.7 1996/05/07 09:15:09 fritz - * Reorganized and general cleanup. - * Bugfixes: - * - Audio-transmit working now. - * - "NO CARRIER" now reported, when hanging up with DTR low. - * - Corrected CTS handling. - * - * Revision 1.6 1996/05/02 03:59:25 fritz - * Bugfixes: - * - On dialout, layer-2 setup had been incomplete - * when using new auto-layer2 feature. - * - On hangup, "NO CARRIER" message sometimes missing. - * - * Revision 1.5 1996/04/30 21:05:25 fritz - * Test commit - * - * Revision 1.4 1996/04/20 16:39:54 fritz - * Changed all io to go through generic routines in isdn_common.c - * Fixed a real ugly bug in modem-emulator: 'ATA' had been accepted - * even when a call has been cancelled from the remote machine. - * - * Revision 1.3 1996/02/11 02:12:32 fritz - * Bugfixes according to similar fixes in standard serial.c of kernel. - * - * Revision 1.2 1996/01/22 05:12:25 fritz - * replaced my_atoi by simple_strtoul - * - * Revision 1.1 1996/01/09 04:13:18 fritz - * Initial revision - * */ #undef ISDN_TTY_STAT_DEBUG @@ -394,7 +66,7 @@ static int si2bit[8] = {4, 1, 4, 4, 4, 4, 4, 4}; -char *isdn_tty_revision = "$Revision: 1.84 $"; +char *isdn_tty_revision = "$Revision: 1.93 $"; /* isdn_tty_try_read() is called from within isdn_tty_rcv_skb() @@ -1511,6 +1183,7 @@ int c; int total = 0; modem_info *info = (modem_info *) tty->driver_data; + atemu *m = &info->emu; if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_write")) return 0; @@ -1531,8 +1204,6 @@ || (info->vonline & 3) #endif ) { - atemu *m = &info->emu; - #ifdef CONFIG_ISDN_AUDIO if (!info->vonline) #endif @@ -1590,7 +1261,9 @@ isdn_command(&c); } info->vonline = 0; - printk(KERN_DEBUG "fax dle cc/c %d/%d\n", cc,c); +#ifdef ISDN_DEBUG_MODEM_VOICE + printk(KERN_DEBUG "fax dle cc/c %d/%d\n", cc, c); +#endif info->xmit_count += cc; } else #endif @@ -1612,9 +1285,14 @@ count -= c; total += c; } - if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue))) - isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1); atomic_dec(&info->xmit_lock); + if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue))) { + if (m->mdmreg[REG_DXMT] & BIT_DXMT) { + isdn_tty_senddown(info); + isdn_tty_tint(info); + } + isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1); + } if (from_user) up(&info->write_sem); return total; @@ -2485,7 +2163,7 @@ while (1) { if ((q = strchr(p, ';'))) *q = '\0'; - if ((tmp = isdn_wildmat(cid, isdn_map_eaz2msn(p, di))) > ret) + if ((tmp = isdn_msncmp(cid, isdn_map_eaz2msn(p, di))) > ret) ret = tmp; #ifdef ISDN_DEBUG_MODEM_ICALL printk(KERN_DEBUG "m_fi: lmsnX=%s mmsn=%s -> tmp=%d\n", @@ -2504,7 +2182,7 @@ return ret; } else { int tmp; - tmp = isdn_wildmat(cid, isdn_map_eaz2msn(emu->msn, di)); + tmp = isdn_msncmp(cid, isdn_map_eaz2msn(emu->msn, di)); #ifdef ISDN_DEBUG_MODEM_ICALL printk(KERN_DEBUG "m_fi: mmsn=%s -> tmp=%d\n", isdn_map_eaz2msn(emu->msn, di), tmp); @@ -2525,7 +2203,7 @@ * CID is longer. */ int -isdn_tty_find_icall(int di, int ch, setup_parm setup) +isdn_tty_find_icall(int di, int ch, setup_parm *setup) { char *eaz; int i; @@ -2536,18 +2214,18 @@ char *nr; ulong flags; - if (!setup.phone[0]) { + if (!setup->phone[0]) { nr = "0"; printk(KERN_INFO "isdn_tty: Incoming call without OAD, assuming '0'\n"); } else - nr = setup.phone; - si1 = (int) setup.si1; - si2 = (int) setup.si2; - if (!setup.eazmsn[0]) { + nr = setup->phone; + si1 = (int) setup->si1; + si2 = (int) setup->si2; + if (!setup->eazmsn[0]) { printk(KERN_WARNING "isdn_tty: Incoming call without CPN, assuming '0'\n"); eaz = "0"; } else - eaz = setup.eazmsn; + eaz = setup->eazmsn; #ifdef ISDN_DEBUG_MODEM_ICALL printk(KERN_DEBUG "m_fi: eaz=%s si1=%d si2=%d\n", eaz, si1, si2); #endif @@ -2589,8 +2267,8 @@ strcpy(dev->num[idx], nr); strcpy(info->emu.cpn, eaz); info->emu.mdmreg[REG_SI1I] = si2bit[si1]; - info->emu.mdmreg[REG_PLAN] = setup.plan; - info->emu.mdmreg[REG_SCREEN] = setup.screen; + info->emu.mdmreg[REG_PLAN] = setup->plan; + info->emu.mdmreg[REG_SCREEN] = setup->screen; isdn_info_update(); restore_flags(flags); printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr, @@ -2697,11 +2375,21 @@ #ifdef ISDN_TTY_STAT_DEBUG printk(KERN_DEBUG "tty_STAT_BCONN ttyI%d\n", info->line); #endif + /* Wake up any processes waiting + * for incoming call of this device when + * DCD follow the state of incoming carrier + */ + if (info->blocked_open && + (info->emu.mdmreg[REG_DCD] & BIT_DCD)) { + wake_up_interruptible(&info->open_wait); + } + /* Schedule CONNECT-Message to any tty * waiting for it and * set DCD-bit of its modem-status. */ - if (TTY_IS_ACTIVE(info)) { + if (TTY_IS_ACTIVE(info) || + (info->blocked_open && (info->emu.mdmreg[REG_DCD] & BIT_DCD))) { info->msr |= UART_MSR_DCD; info->emu.charge = 0; if (info->dialing & 0xf) @@ -3155,8 +2843,8 @@ int limit = ISDN_MSNLEN - 1; while (((*p[0] >= '0' && *p[0] <= '9') || - /* Why a comma ??? */ - (*p[0] == ',')) && + /* Why a comma ??? */ + (*p[0] == ',') || (*p[0] == ':')) && (limit--)) *n++ = *p[0]++; *n = '\0'; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/isdn_tty.h linux/drivers/isdn/isdn_tty.h --- v2.4.0-test5/linux/drivers/isdn/isdn_tty.h Sat Feb 26 22:31:46 2000 +++ linux/drivers/isdn/isdn_tty.h Tue Aug 8 15:03:57 2000 @@ -1,4 +1,4 @@ -/* $Id: isdn_tty.h,v 1.19 2000/02/16 14:59:33 paul Exp $ +/* $Id: isdn_tty.h,v 1.22 2000/06/21 09:54:29 keil Exp $ * header for Linux ISDN subsystem, tty related functions (linklevel). * @@ -19,89 +19,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Log: isdn_tty.h,v $ - * Revision 1.19 2000/02/16 14:59:33 paul - * translated ISDN_MODEM_ANZREG to ISDN_MODEM_NUMREG for english speakers; - * used defines for result codes; - * fixed RING ... RUNG problem (no empty lines in between). - * - * Revision 1.18 2000/01/20 19:55:33 keil - * Add FAX Class 1 support - * - * Revision 1.17 1999/09/21 19:00:35 armin - * Extended FCON message with added CPN - * can now be activated with Bit 1 of Reg 23. - * - * Revision 1.16 1999/08/22 20:26:10 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.15 1999/07/31 12:59:48 armin - * Added tty fax capabilities. - * - * Revision 1.14 1999/07/11 17:14:15 armin - * Added new layer 2 and 3 protocols for Fax and DSP functions. - * Moved "Add CPN to RING message" to new register S23, - * "Display message" is now correct on register S13 bit 7. - * New audio command AT+VDD implemented (deactivate DTMF decoder and - * activate possible existing hardware/DSP decoder). - * Moved some tty defines to .h file. - * Made whitespace possible in AT command line. - * Some AT-emulator output bugfixes. - * First Fax G3 implementations. - * - * Revision 1.13 1999/04/12 12:33:46 fritz - * Changes from 2.0 tree. - * - * Revision 1.12 1999/03/02 12:04:51 armin - * -added ISDN_STAT_ADDCH to increase supported channels after - * register_isdn(). - * -ttyI now goes on-hook on ATZ when B-Ch is connected. - * -added timer-function for register S7 (Wait for Carrier). - * -analog modem (ISDN_PROTO_L2_MODEM) implementations. - * -on L2_MODEM a string will be appended to the CONNECT-Message, - * which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN. - * -variable "dialing" used for ATA also, for interrupting call - * establishment and register S7. - * - * Revision 1.11 1998/03/19 13:18:27 keil - * Start of a CAPI like interface for supplementary Service - * first service: SUSPEND - * - * Revision 1.10 1997/03/02 14:29:26 fritz - * More ttyI related cleanup. - * - * Revision 1.9 1997/02/28 02:32:49 fritz - * Cleanup: Moved some tty related stuff from isdn_common.c - * to isdn_tty.c - * Bugfix: Bisync protocol did not behave like documented. - * - * Revision 1.8 1997/02/10 20:12:50 fritz - * Changed interface for reporting incoming calls. - * - * Revision 1.7 1997/02/03 23:06:10 fritz - * Reformatted according CodingStyle - * - * Revision 1.6 1997/01/14 01:35:19 fritz - * Changed prototype of isdn_tty_modem_hup. - * - * Revision 1.5 1996/05/17 03:52:31 fritz - * Changed DLE handling for audio receive. - * - * Revision 1.4 1996/05/11 21:52:34 fritz - * Changed queue management to use sk_buffs. - * - * Revision 1.3 1996/05/07 09:16:34 fritz - * Changed isdn_try_read parameter. - * - * Revision 1.2 1996/04/30 21:05:27 fritz - * Test commit - * - * Revision 1.1 1996/01/10 21:39:22 fritz - * Initial revision - * */ #include @@ -140,6 +57,8 @@ #define REG_CPPP 12 #define BIT_CPPP 128 +#define REG_DXMT 13 +#define BIT_DXMT 1 #define REG_T70 13 #define BIT_T70 2 #define BIT_T70_EXT 32 @@ -196,7 +115,7 @@ extern void isdn_tty_modem_xmit(void); extern int isdn_tty_modem_init(void); extern void isdn_tty_readmodem(void); -extern int isdn_tty_find_icall(int, int, setup_parm); +extern int isdn_tty_find_icall(int, int, setup_parm *); extern void isdn_tty_cleanup_xmit(modem_info *); extern int isdn_tty_stat_callback(int, isdn_ctrl *); extern int isdn_tty_rcv_skb(int, int, int, struct sk_buff *); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/isdn_ttyfax.c linux/drivers/isdn/isdn_ttyfax.c --- v2.4.0-test5/linux/drivers/isdn/isdn_ttyfax.c Wed Feb 16 17:03:52 2000 +++ linux/drivers/isdn/isdn_ttyfax.c Sun Aug 6 12:43:42 2000 @@ -1,4 +1,5 @@ -/* $Id: isdn_ttyfax.c,v 1.6 2000/01/26 00:41:13 keil Exp $ +/* $Id: isdn_ttyfax.c,v 1.7 2000/05/11 22:29:21 kai Exp $ + * Linux ISDN subsystem, tty_fax AT-command emulator (linklevel). * * Copyright 1999 by Armin Schindler (mac@melware.de) @@ -19,30 +20,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Log: isdn_ttyfax.c,v $ - * Revision 1.6 2000/01/26 00:41:13 keil - * add "00" as dummy msn in isdn_get_free_channel call - * - * Revision 1.5 2000/01/20 19:55:33 keil - * Add FAX Class 1 support - * - * Revision 1.4 1999/09/21 19:00:35 armin - * Extended FCON message with added CPN - * can now be activated with Bit 1 of Reg 23. - * - * Revision 1.3 1999/08/22 20:26:12 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.2 1999/08/05 10:36:10 armin - * Bugfix: kernel oops on getting revision. - * - * Revision 1.1 1999/07/31 12:59:50 armin - * Added tty fax capabilities. - * - * */ #undef ISDN_TTY_FAX_STAT_DEBUG @@ -56,7 +33,7 @@ #include "isdn_ttyfax.h" -static char *isdn_tty_fax_revision = "$Revision: 1.6 $"; +static char *isdn_tty_fax_revision = "$Revision: 1.7 $"; #define PARSE_ERROR1 { isdn_tty_fax_modem_result(1, info); return 1; } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/isdn_ttyfax.h linux/drivers/isdn/isdn_ttyfax.h --- v2.4.0-test5/linux/drivers/isdn/isdn_ttyfax.h Thu Aug 12 09:42:33 1999 +++ linux/drivers/isdn/isdn_ttyfax.h Sun Aug 6 12:43:42 2000 @@ -1,4 +1,5 @@ -/* $Id: isdn_ttyfax.h,v 1.1 1999/07/31 12:59:51 armin Exp $ +/* $Id: isdn_ttyfax.h,v 1.2 2000/05/11 22:29:21 kai Exp $ + * header for Linux ISDN subsystem, tty_fax related functions (linklevel). * * Copyright 1999 by Armin Schindler (mac@melware.de) @@ -18,11 +19,6 @@ * 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. - * - * $Log: isdn_ttyfax.h,v $ - * Revision 1.1 1999/07/31 12:59:51 armin - * Added tty fax capabilities. - * * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/isdn_v110.c linux/drivers/isdn/isdn_v110.c --- v2.4.0-test5/linux/drivers/isdn/isdn_v110.c Mon Mar 27 08:08:25 2000 +++ linux/drivers/isdn/isdn_v110.c Sun Aug 6 12:43:42 2000 @@ -1,4 +1,4 @@ -/* $Id: isdn_v110.c,v 1.4 2000/03/16 16:34:12 kai Exp $ +/* $Id: isdn_v110.c,v 1.5 2000/05/11 22:29:21 kai Exp $ * Linux ISDN subsystem, V.110 related functions (linklevel). * @@ -18,22 +18,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Log: isdn_v110.c,v $ - * Revision 1.4 2000/03/16 16:34:12 kai - * some translation work - * - * there shouldn't be any German comments lurking around anymore ;-) - * - * Revision 1.3 1999/10/30 09:49:28 keil - * Reinit of v110 structs - * - * Revision 1.2 1998/02/22 19:44:25 fritz - * Bugfixes and improvements regarding V.110, V.110 now running. - * - * Revision 1.1 1998/02/20 17:32:09 fritz - * First checkin (not yet completely functionable). - * */ + #include #include #include @@ -44,7 +30,7 @@ #undef ISDN_V110_DEBUG -char *isdn_v110_revision = "$Revision: 1.4 $"; +char *isdn_v110_revision = "$Revision: 1.5 $"; #define V110_38400 255 #define V110_19200 15 diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/isdn_v110.h linux/drivers/isdn/isdn_v110.h --- v2.4.0-test5/linux/drivers/isdn/isdn_v110.h Mon Mar 27 08:08:25 2000 +++ linux/drivers/isdn/isdn_v110.h Sun Aug 6 12:43:42 2000 @@ -1,4 +1,4 @@ -/* $Id: isdn_v110.h,v 1.3 2000/03/16 16:34:12 kai Exp $ +/* $Id: isdn_v110.h,v 1.4 2000/05/11 22:29:21 kai Exp $ * Linux ISDN subsystem, V.110 related functions (linklevel). * @@ -17,18 +17,6 @@ * 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. - * - * $Log: isdn_v110.h,v $ - * Revision 1.3 2000/03/16 16:34:12 kai - * some translation work - * - * there shouldn't be any German comments lurking around anymore ;-) - * - * Revision 1.2 1999/10/30 09:49:28 keil - * Reinit of v110 structs - * - * Revision 1.1 1998/02/20 17:32:11 fritz - * First checkin (not yet completely functionable). * */ #ifndef _isdn_v110_h_ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/isdn_x25iface.c linux/drivers/isdn/isdn_x25iface.c --- v2.4.0-test5/linux/drivers/isdn/isdn_x25iface.c Thu Aug 26 13:05:37 1999 +++ linux/drivers/isdn/isdn_x25iface.c Sun Aug 6 12:43:42 2000 @@ -1,4 +1,23 @@ -/* $Id: isdn_x25iface.c,v 1.7 1999/08/22 20:26:13 calle Exp $ +/* $Id: isdn_x25iface.c,v 1.9 2000/05/16 20:52:10 keil Exp $ + + * + * Linux ISDN subsystem, X.25 related functions + * + * 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, 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. + * + * * stuff needed to support the Linux X.25 PLP code on top of devices that * can provide a lab_b service using the concap_proto mechanism. * This module supports a network interface wich provides lapb_sematics @@ -8,33 +27,6 @@ * * Only protocol specific stuff goes here. Device specific stuff * goes to another -- device related -- concap_proto support source file. - * - * $Log: isdn_x25iface.c,v $ - * Revision 1.7 1999/08/22 20:26:13 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.6 1999/01/27 22:53:19 he - * minor updates (spellings, jiffies wrap around in isdn_tty) - * - * Revision 1.5 1998/10/30 17:55:39 he - * dialmode for x25iface and multulink ppp - * - * Revision 1.4 1998/06/17 19:51:00 he - * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay()) - * brute force fix to avoid Ugh's in isdn_tty_write() - * cleaned up some dead code - * - * Revision 1.3 1998/02/20 17:25:20 fritz - * Changes for recent kernels. - * - * Revision 1.2 1998/01/31 22:49:22 keil - * correct comments - * - * Revision 1.1 1998/01/31 22:27:58 keil - * New files from Henner Eisen for X.25 support * */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/isdn/isdn_x25iface.h linux/drivers/isdn/isdn_x25iface.h --- v2.4.0-test5/linux/drivers/isdn/isdn_x25iface.h Wed Apr 1 16:21:03 1998 +++ linux/drivers/isdn/isdn_x25iface.h Sun Aug 6 12:43:42 2000 @@ -1,5 +1,23 @@ -/* $Id: isdn_x25iface.h,v 1.2 1998/01/31 22:49:23 keil Exp $ +/* $Id: isdn_x25iface.h,v 1.3 2000/05/11 22:29:21 kai Exp $ + + * header for Linux ISDN subsystem, x.25 related functions + * + * 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, 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. + * */ + #ifndef _LINUX_ISDN_X25IFACE_H #define _LINUX_ISDN_X25IFACE_H diff -u --recursive --new-file v2.4.0-test5/linux/drivers/mtd/Makefile linux/drivers/mtd/Makefile --- v2.4.0-test5/linux/drivers/mtd/Makefile Thu Jul 27 17:38:00 2000 +++ linux/drivers/mtd/Makefile Sun Aug 6 11:23:40 2000 @@ -43,7 +43,6 @@ SUB_DIRS := ALL_SUB_DIRS := MOD_SUB_DIRS := -MOD_LIST_NAME := MTD_MODULES export-objs := mtdcore.o doc2000.o doc2001.o cfi_probe.o cfi_cmdset_0001.o cfi_cmdset_0002.o list-multi := diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/82596.c linux/drivers/net/82596.c --- v2.4.0-test5/linux/drivers/net/82596.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/82596.c Mon Aug 7 23:02:56 2000 @@ -706,8 +706,10 @@ spin_lock_irqsave (&lp->lock, flags); - if (wait_cmd(dev,lp,1000,"timed out waiting to issue RX_START")) + if (wait_cmd(dev,lp,1000,"timed out waiting to issue RX_START")) { + spin_unlock_irqrestore (&lp->lock, flags); goto failed; + } DEB(DEB_INIT,printk("%s: Issuing RX_START\n", dev->name)); lp->scb.command = RX_START; CA(dev); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/Config.in linux/drivers/net/Config.in --- v2.4.0-test5/linux/drivers/net/Config.in Mon Jul 10 16:47:23 2000 +++ linux/drivers/net/Config.in Wed Aug 9 13:59:04 2000 @@ -51,7 +51,7 @@ if [ "$CONFIG_SGI_IP27" = "y" ]; then bool ' SGI IOC3 Ethernet' CONFIG_SGI_IOC3_ETH fi - if [ "$CONFIG_SUPERH" = "y" -a "$CONFIG_SH_SOLUTION_ENGINE" = "y" ]; then + if [ "$CONFIG_SUPERH" = "y" ]; then tristate ' National DP83902AV support' CONFIG_STNIC fi bool ' 3COM cards' CONFIG_NET_VENDOR_3COM diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/Makefile linux/drivers/net/Makefile --- v2.4.0-test5/linux/drivers/net/Makefile Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/Makefile Sun Aug 6 11:23:40 2000 @@ -21,7 +21,6 @@ arcnet skfp tulip appletalk O_TARGET := net.o -MOD_LIST_NAME := NET_MODULES # All of the (potential) objects that export symbols. # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'. diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/acenic.c linux/drivers/net/acenic.c --- v2.4.0-test5/linux/drivers/net/acenic.c Tue May 23 15:31:35 2000 +++ linux/drivers/net/acenic.c Fri Jul 28 12:47:19 2000 @@ -607,6 +607,7 @@ MODULE_PARM(rx_coal_tick, "1-" __MODULE_STRING(8) "i"); MODULE_PARM(max_rx_desc, "1-" __MODULE_STRING(8) "i"); +#endif void __exit ace_module_cleanup(void) { @@ -695,7 +696,6 @@ root_dev = next; } } -#endif int __init ace_module_init(void) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/appletalk/cops.c linux/drivers/net/appletalk/cops.c --- v2.4.0-test5/linux/drivers/net/appletalk/cops.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/net/appletalk/cops.c Sun Aug 6 22:20:09 2000 @@ -772,6 +772,7 @@ if(boguscount==1000000) { printk(KERN_WARNING "%s: DMA timed out.\n",dev->name); + restore_flags(flags); return; } } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/appletalk/ltpc.c linux/drivers/net/appletalk/ltpc.c --- v2.4.0-test5/linux/drivers/net/appletalk/ltpc.c Mon Jul 10 16:47:23 2000 +++ linux/drivers/net/appletalk/ltpc.c Fri Aug 4 18:18:48 2000 @@ -1273,18 +1273,18 @@ __setup("ltpc=", ltpc_setup); #endif /* MODULE */ -MODULE_PARM(debug, "i"); -MODULE_PARM(io, "i"); -MODULE_PARM(irq, "i"); -MODULE_PARM(dma, "i"); - -#ifdef MODULE - static struct net_device dev_ltpc = { "", 0, 0, 0, 0, 0x0, 0, 0, 0, 0, NULL, ltpc_probe }; + +#ifdef MODULE +MODULE_PARM(debug, "i"); +MODULE_PARM(io, "i"); +MODULE_PARM(irq, "i"); +MODULE_PARM(dma, "i"); + int __init init_module(void) { diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/at1700.c linux/drivers/net/at1700.c --- v2.4.0-test5/linux/drivers/net/at1700.c Fri Jul 14 12:12:10 2000 +++ linux/drivers/net/at1700.c Sat Aug 5 22:49:32 2000 @@ -557,7 +557,8 @@ /* ToDo: We should try to restart the adaptor... */ outw (0xffff, ioaddr + 24); outw (0xffff, ioaddr + TX_STATUS); - outw (0xe85a, ioaddr + CONFIG_0); + outb (0x5a, ioaddr + CONFIG_0); + outb (0xe8, ioaddr + CONFIG_1); outw (0x8182, ioaddr + TX_INTR); outb (0x00, ioaddr + TX_START); outb (0x03, ioaddr + COL16CNTL); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/bmac.c linux/drivers/net/bmac.c --- v2.4.0-test5/linux/drivers/net/bmac.c Sun Feb 13 19:29:04 2000 +++ linux/drivers/net/bmac.c Wed Aug 9 13:49:28 2000 @@ -1292,6 +1292,12 @@ dev = init_etherdev(NULL, PRIV_BYTES); + if (!dev) { + printk(KERN_ERR "init_etherdev failed, out of memory for BMAC %s\n", + bmac->full_name); + return; + } + dev->base_addr = (unsigned long) ioremap(bmac->addrs[0].address, bmac->addrs[0].size); dev->irq = bmac->intrs[0].line; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/eepro100.c linux/drivers/net/eepro100.c --- v2.4.0-test5/linux/drivers/net/eepro100.c Fri Jul 14 12:12:10 2000 +++ linux/drivers/net/eepro100.c Wed Aug 9 13:49:28 2000 @@ -568,8 +568,11 @@ static int eepro100_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static void eepro100_remove_one (struct pci_dev *pdev); + +#ifdef CONFIG_EEPRO100_PM static void eepro100_suspend (struct pci_dev *pdev); static void eepro100_resume (struct pci_dev *pdev); +#endif /* CONFIG_EEPRO100_PM */ static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len); static int mdio_read(long ioaddr, int phy_id, int location); @@ -2182,6 +2185,9 @@ sp->rx_mode = new_rx_mode; } + +#ifdef CONFIG_EEPRO100_PM + static void eepro100_suspend(struct pci_dev *pdev) { struct net_device *dev = pdev->driver_data; @@ -2214,6 +2220,8 @@ set_rx_mode(dev); } +#endif /* CONFIG_EEPRO100_PM */ + static void __devexit eepro100_remove_one (struct pci_dev *pdev) { struct net_device *dev = pdev->driver_data; @@ -2252,8 +2260,11 @@ id_table: eepro100_pci_tbl, probe: eepro100_init_one, remove: eepro100_remove_one, + +#ifdef CONFIG_EEPRO100_PM suspend: eepro100_suspend, resume: eepro100_resume, +#endif }; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,48) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/eth16i.c linux/drivers/net/eth16i.c --- v2.4.0-test5/linux/drivers/net/eth16i.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/eth16i.c Tue Aug 8 09:31:00 2000 @@ -663,7 +663,7 @@ { int i; int retcode; - unsigned char dummy_packet[64] = { 0 }; + unsigned char dummy_packet[64]; /* Powerup the chip */ outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1); @@ -679,6 +679,7 @@ dummy_packet[12] = 0x00; dummy_packet[13] = 0x04; + memset(dummy_packet + 14, 0, sizeof(dummy_packet) - 14); eth16i_select_regbank(2, ioaddr); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/fc/Makefile linux/drivers/net/fc/Makefile --- v2.4.0-test5/linux/drivers/net/fc/Makefile Thu Aug 26 13:05:38 1999 +++ linux/drivers/net/fc/Makefile Sun Aug 6 11:23:40 2000 @@ -10,7 +10,6 @@ L_OBJS := M_OBJS := MX_OBJS := -MOD_LIST_NAME := FC_MODULES FC_SRCS = $(wildcard $(L_OBJS:%.o=%.c)) ifeq ($(CONFIG_IPHASE5526),y) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/fc/iph5526.c linux/drivers/net/fc/iph5526.c --- v2.4.0-test5/linux/drivers/net/fc/iph5526.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/net/fc/iph5526.c Sat Aug 5 08:39:14 2000 @@ -3952,8 +3952,10 @@ /* Get an used OX_ID. We could have pending commands. */ - if (get_scsi_oxid(fi)) + if (get_scsi_oxid(fi)) { + spin_unlock_irqrestore(&fi->fc_lock, flags); return 1; + } fi->q.free_scsi_oxid[fi->g.scsi_oxid] = OXID_INUSE; /* Maintain a handler so that we can associate the done() function diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/gmac.c linux/drivers/net/gmac.c --- v2.4.0-test5/linux/drivers/net/gmac.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/net/gmac.c Wed Aug 9 13:49:29 2000 @@ -5,12 +5,14 @@ * Copyright (C) 2000 Paul Mackerras & Ben. Herrenschmidt * * portions based on sunhme.c by David S. Miller + * + * Changes: + * Arnaldo Carvalho de Melo - 08/06/2000 + * - check init_etherdev return in gmac_probe1 * */ #include - -#include #include #include #include @@ -1180,7 +1182,13 @@ } dev = init_etherdev(0, sizeof(struct gmac)); - memset(dev->priv, 0, sizeof(struct gmac)); + + if (!dev) { + printk(KERN_ERR "GMAC: init_etherdev failed, out of memory\n"); + free_page(tx_descpage); + free_page(rx_descpage); + return; + } gm = (struct gmac *) dev->priv; dev->base_addr = gmac->addrs[0].address; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/hamradio/Makefile linux/drivers/net/hamradio/Makefile --- v2.4.0-test5/linux/drivers/net/hamradio/Makefile Thu Aug 12 12:19:41 1999 +++ linux/drivers/net/hamradio/Makefile Sun Aug 6 11:23:40 2000 @@ -14,7 +14,6 @@ O_TARGET := hamradio.o O_OBJS := M_OBJS := -MOD_LIST_NAME := HAM_MODULES # Need these to keep track of whether the hdlc module should # really go in the kernel or a module. diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/hydra.c linux/drivers/net/hydra.c --- v2.4.0-test5/linux/drivers/net/hydra.c Sun Feb 13 19:29:04 2000 +++ linux/drivers/net/hydra.c Wed Aug 9 13:49:29 2000 @@ -13,6 +13,11 @@ /* The Amiganet is a Zorro-II board made by Hydra Systems. It contains a */ /* NS8390 NIC (network interface controller) clone, 16 or 64K on-board RAM */ /* and 10BASE-2 (thin coax) and AUI connectors. */ +/* */ +/* Changes */ +/* Arnaldo Carvalho de Melo - 08/06/2000 */ +/* - check init_etherdev in hydra_probe */ +/* - dev->priv is already zeroed by init_etherdev */ #include @@ -176,8 +181,13 @@ strcpy(z->name, "Hydra Ethernet Card"); dev = init_etherdev(NULL, sizeof(struct hydra_private)); - memset(dev->priv, 0, sizeof(struct hydra_private)); - + + if (!dev) { + release_mem_region(base_addr, 0x20); + release_mem_region(board, 0x4000); + continue; + } + for(j = 0; j < ETHER_ADDR_LEN; j++) dev->dev_addr[j] = *((u8 *)ZTWO_VADDR(board + HYDRA_ADDRPROM + 2*j)); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/ioc3-eth.c linux/drivers/net/ioc3-eth.c --- v2.4.0-test5/linux/drivers/net/ioc3-eth.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/ioc3-eth.c Thu Jul 27 18:36:54 2000 @@ -105,8 +105,6 @@ static void ioc3_timeout(struct net_device *dev); static inline unsigned int ioc3_hash(const unsigned char *addr); static void ioc3_stop(struct net_device *dev); -static void ioc3_clean_tx_ring(struct ioc3_private *ip); -static void ioc3_clean_rx_ring(struct ioc3_private *ip); static void ioc3_init(struct net_device *dev); static const char ioc3_str[] = "IOC3 Ethernet"; @@ -446,7 +444,6 @@ ip->stats.rx_packets++; /* Statistics */ ip->stats.rx_bytes += len; - } else { /* The frame is invalid and the skb never reached the network layer so we can just @@ -464,7 +461,6 @@ ((unsigned long) rxb & TO_PHYS_MASK); rxb->w0 = 0; /* Clear valid flag */ n_entry = (n_entry + 1) & 511; /* Update erpir */ - ioc3->erpir = (n_entry << 3) | ERPIR_ARM; /* Now go on to the next ring entry. */ rx_entry = (rx_entry + 1) & 511; @@ -472,6 +468,7 @@ rxb = (struct ioc3_erxbuf *) (skb->data - RX_OFFSET); w0 = rxb->w0; } + ioc3->erpir = (n_entry << 3) | ERPIR_ARM; ip->rx_pi = n_entry; ip->rx_ci = rx_entry; } @@ -527,17 +524,26 @@ ioc3_error(struct net_device *dev, struct ioc3_private *ip, struct ioc3 *ioc3, u32 eisr) { - if (eisr & (EISR_RXMEMERR | EISR_TXMEMERR)) { - if (eisr & EISR_RXMEMERR) { - printk(KERN_ERR "%s: RX PCI error.\n", dev->name); - } - if (eisr & EISR_TXMEMERR) { - printk(KERN_ERR "%s: TX PCI error.\n", dev->name); - } + if (eisr & EISR_RXOFLO) { + printk(KERN_ERR "%s: RX overflow.\n", dev->name); + } + if (eisr & EISR_RXBUFOFLO) { + printk(KERN_ERR "%s: RX buffer overflow.\n", dev->name); + } + if (eisr & EISR_RXMEMERR) { + printk(KERN_ERR "%s: RX PCI error.\n", dev->name); + } + if (eisr & EISR_RXPARERR) { + printk(KERN_ERR "%s: RX SSRAM parity error.\n", dev->name); + } + if (eisr & EISR_TXBUFUFLO) { + printk(KERN_ERR "%s: TX buffer underflow.\n", dev->name); + } + if (eisr & EISR_TXMEMERR) { + printk(KERN_ERR "%s: TX PCI error.\n", dev->name); } ioc3_stop(dev); - ioc3_clean_tx_ring(dev->priv); ioc3_init(dev); dev->trans_start = jiffies; @@ -551,8 +557,9 @@ struct net_device *dev = (struct net_device *)_dev; struct ioc3_private *ip = dev->priv; struct ioc3 *ioc3 = ip->regs; - const u32 enabled = EISR_RXTIMERINT | EISR_TXEXPLICIT | - EISR_RXMEMERR | EISR_TXMEMERR; + const u32 enabled = EISR_RXTIMERINT | EISR_RXOFLO | EISR_RXBUFOFLO | + EISR_RXMEMERR | EISR_RXPARERR | EISR_TXBUFUFLO | + EISR_TXEXPLICIT | EISR_TXMEMERR; u32 eisr; eisr = ioc3->eisr & enabled; @@ -560,12 +567,14 @@ ioc3->eisr = eisr; ioc3->eisr; /* Flush */ + if (eisr & (EISR_RXOFLO | EISR_RXBUFOFLO | EISR_RXMEMERR | + EISR_RXPARERR | EISR_TXBUFUFLO | EISR_TXMEMERR)) + ioc3_error(dev, ip, ioc3, eisr); if (eisr & EISR_RXTIMERINT) ioc3_rx(dev, ip, ioc3); if (eisr & EISR_TXEXPLICIT) ioc3_tx(dev, ip, ioc3); - if (eisr & (EISR_RXMEMERR | EISR_TXMEMERR)) - ioc3_error(dev, ip, ioc3, eisr); + eisr = ioc3->eisr & enabled; } } @@ -612,15 +621,73 @@ mii_write(ioc3, phy, 0, mii0 | 0x3100); spin_unlock_irq(&ip->ioc3_lock); - mdelay(1000); /* XXX Yikes XXX */ - spin_lock_irq(&ip->ioc3_lock); - - mii_status = mii_read(ioc3, phy, 1); - spin_unlock_irq(&ip->ioc3_lock); return 0; } +static inline void +ioc3_clean_rx_ring(struct ioc3_private *ip) +{ + struct sk_buff *skb; + int i; + + for (i = ip->rx_ci; i & 15; i++) { + ip->rx_skbs[ip->rx_pi] = ip->rx_skbs[ip->rx_ci]; + ip->rxr[ip->rx_pi++] = ip->rxr[ip->rx_ci++]; + } + ip->rx_pi &= 511; + ip->rx_ci &= 511; + + for (i = ip->rx_ci; i != ip->rx_pi; i = (i+1) & 511) { + struct ioc3_erxbuf *rxb; + skb = ip->rx_skbs[i]; + rxb = (struct ioc3_erxbuf *) (skb->data - RX_OFFSET); + rxb->w0 = 0; + } +} + +static inline void +ioc3_clean_tx_ring(struct ioc3_private *ip) +{ + struct sk_buff *skb; + int i; + + for (i=0; i < 128; i++) { + skb = ip->tx_skbs[i]; + if (skb) { + ip->tx_skbs[i] = NULL; + dev_kfree_skb_any(skb); + } + ip->txr[i].cmd = 0; + } + ip->tx_pi = 0; + ip->tx_ci = 0; +} + +static void +ioc3_free_rings(struct ioc3_private *ip) +{ + struct sk_buff *skb; + int rx_entry, n_entry; + + ioc3_clean_tx_ring(ip); + ip->txr = NULL; + free_pages((unsigned long)ip->txr, 2); + + n_entry = ip->rx_ci; + rx_entry = ip->rx_pi; + + while (n_entry != rx_entry) { + skb = ip->rx_skbs[n_entry]; + if (skb) + dev_kfree_skb_any(skb); + + n_entry = (n_entry + 1) & 511; + } + free_page((unsigned long)ip->rxr); + ip->rxr = NULL; +} + static void ioc3_alloc_rings(struct net_device *dev, struct ioc3_private *ip, struct ioc3 *ioc3) @@ -676,8 +743,8 @@ ioc3_alloc_rings(dev, ip, ioc3); - ioc3_clean_tx_ring(ip); ioc3_clean_rx_ring(ip); + ioc3_clean_tx_ring(ip); /* Now the rx ring base, consume & produce registers. */ ring = (0xa5UL << 56) | ((unsigned long)ip->rxr & TO_PHYS_MASK); @@ -698,61 +765,6 @@ ioc3->etcir; /* Flush */ } -static void -ioc3_clean_tx_ring(struct ioc3_private *ip) -{ - struct sk_buff *skb; - int i; - - for (i=0; i < 128; i++) { - skb = ip->tx_skbs[i]; - if (skb) { - ip->tx_skbs[i] = NULL; - dev_kfree_skb_any(skb); - } - ip->txr[i].cmd = 0; - } -} - -static void -ioc3_clean_rx_ring(struct ioc3_private *ip) -{ - struct sk_buff *skb; - int i; - - for (i = 0; i < RX_BUFFS; i++) { - struct ioc3_erxbuf *rxb; - skb = ip->rx_skbs[i]; - rxb = (struct ioc3_erxbuf *) (skb->data - RX_OFFSET); - - rxb->w0 = 0; - } -} - -static void -ioc3_free_rings(struct ioc3_private *ip) -{ - struct sk_buff *skb; - int rx_entry, n_entry; - - ioc3_clean_tx_ring(ip); - free_pages((unsigned long)ip->txr, 2); - ip->txr = NULL; - - n_entry = ip->rx_ci; - rx_entry = ip->rx_pi; - - while (n_entry != rx_entry) { - skb = ip->rx_skbs[n_entry]; - if (skb) - dev_kfree_skb_any(skb); - - n_entry = (n_entry + 1) & 511; - } - free_page((unsigned long)ip->rxr); - ip->rxr = NULL; -} - static inline void ioc3_ssram_disc(struct ioc3_private *ip) { @@ -797,17 +809,18 @@ ioc3->emar_h = (dev->dev_addr[5] << 8) | dev->dev_addr[4]; ioc3->emar_l = (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | dev->dev_addr[0]; - ioc3->ehar_h = ioc3->ehar_l = 0; + ioc3->ehar_h = ip->ehar_h; + ioc3->ehar_l = ip->ehar_l; ioc3->ersr = 42; /* XXX should be random */ - //ioc3->erpir = ERPIR_ARM; ioc3_init_rings(dev, ip, ioc3); ip->emcr |= ((RX_OFFSET / 2) << EMCR_RXOFF_SHIFT) | EMCR_TXDMAEN | - EMCR_TXEN | EMCR_RXDMAEN | EMCR_RXEN; + EMCR_TXEN | EMCR_RXDMAEN | EMCR_RXEN; ioc3->emcr = ip->emcr; - ioc3->eier = EISR_RXTIMERINT | EISR_TXEXPLICIT | /* Interrupts ... */ - EISR_RXMEMERR | EISR_TXMEMERR; + ioc3->eier = EISR_RXTIMERINT | EISR_RXOFLO | EISR_RXBUFOFLO | + EISR_RXMEMERR | EISR_RXPARERR | EISR_TXBUFUFLO | + EISR_TXEXPLICIT | EISR_TXMEMERR; ioc3->eier; } @@ -817,7 +830,6 @@ struct ioc3 *ioc3 = ip->regs; ioc3->emcr = 0; /* Shutup */ - ip->emcr = 0; ioc3->eier = 0; /* Disable interrupts */ ioc3->eier; /* Flush */ } @@ -825,14 +837,18 @@ static int ioc3_open(struct net_device *dev) { + struct ioc3_private *ip; + if (request_irq(dev->irq, ioc3_interrupt, 0, ioc3_str, dev)) { printk(KERN_ERR "%s: Can't get irq %d\n", dev->name, dev->irq); return -EAGAIN; } - ((struct ioc3_private *)dev->priv)->ehar_h = 0; - ((struct ioc3_private *)dev->priv)->ehar_l = 0; + ip = (struct ioc3_private *) dev->priv; + + ip->ehar_h = 0; + ip->ehar_l = 0; ioc3_init(dev); netif_start_queue(dev); @@ -1005,7 +1021,6 @@ printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name); ioc3_stop(dev); - ioc3_clean_tx_ring(dev->priv); ioc3_init(dev); dev->trans_start = jiffies; @@ -1117,7 +1132,7 @@ if (!(*addr & 1)) continue; - ehar |= (1 << ioc3_hash(addr)); + ehar |= (1UL << ioc3_hash(addr)); } ip->ehar_h = ehar >> 32; ip->ehar_l = ehar & 0xffffffff; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/irda/Makefile linux/drivers/net/irda/Makefile --- v2.4.0-test5/linux/drivers/net/irda/Makefile Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/irda/Makefile Sun Aug 6 11:23:40 2000 @@ -10,7 +10,6 @@ L_TARGET := irda_drivers.a L_OBJS := M_OBJS := -MOD_LIST_NAME := IRDA_DRIVERS_MODULES ifeq ($(CONFIG_IRTTY_SIR),y) L_OBJS += irtty.o diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/pcmcia/Makefile linux/drivers/net/pcmcia/Makefile --- v2.4.0-test5/linux/drivers/net/pcmcia/Makefile Wed Apr 26 16:34:08 2000 +++ linux/drivers/net/pcmcia/Makefile Sun Aug 6 11:23:40 2000 @@ -9,7 +9,6 @@ ALL_SUB_DIRS := $(SUB_DIRS) O_TARGET := pcmcia_net.o -MOD_LIST_NAME := PCMCIA_NET_MODULES obj-y := obj-m := diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/pcmcia/com20020_cs.c linux/drivers/net/pcmcia/com20020_cs.c --- v2.4.0-test5/linux/drivers/net/pcmcia/com20020_cs.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/net/pcmcia/com20020_cs.c Wed Aug 9 13:51:40 2000 @@ -21,6 +21,11 @@ * modified by SRC, incorporated herein by reference. * * ********************** + * Changes: + * Arnaldo Carvalho de Melo - 08/08/2000 + * - reorganize kmallocs in com20020_attach, checking all for failure + * and releasing the previous allocations if one fails + * ********************** * * For more details, see drivers/net/arcnet.c * @@ -198,7 +203,24 @@ link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); if (!link) return NULL; + + info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL); + if (!info) + goto fail_alloc_info; + + lp = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL); + if (!lp) + goto fail_alloc_lp; + + dev = dev_alloc("arc%d", &ret); + if (!dev) + goto fail_alloc_dev; + + memset(info, 0, sizeof(struct com20020_dev_t)); + memset(lp, 0, sizeof(struct arcnet_local)); memset(link, 0, sizeof(struct dev_link_t)); + dev->priv = lp; + link->release.function = &com20020_release; link->release.data = (u_long)link; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; @@ -216,19 +238,6 @@ link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; - info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL); - if (!info) - return NULL; - memset(info, 0, sizeof(struct com20020_dev_t)); - - dev = dev_alloc("arc%d", &ret); - if (!dev) - return NULL; - lp = dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL); - if (!lp) - return NULL; - memset(lp, 0, sizeof(struct arcnet_local)); - /* fill in our module parameters as defaults */ dev->dev_addr[0] = node; lp->timeout = timeout; @@ -260,6 +269,14 @@ } return link; + +fail_alloc_dev: + kfree(lp); +fail_alloc_lp: + kfree(info); +fail_alloc_info: + kfree(link); + return NULL; } /* com20020_attach */ /*====================================================================== diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/pcmcia/ray_cs.c linux/drivers/net/pcmcia/ray_cs.c --- v2.4.0-test5/linux/drivers/net/pcmcia/ray_cs.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/net/pcmcia/ray_cs.c Wed Aug 9 13:49:29 2000 @@ -19,6 +19,12 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Changes: + * Arnaldo Carvalho de Melo - 08/08/2000 + * - reorganize kmallocs in ray_attach, checking all for failure + * and releasing the previous allocations if one fails + * * =============================================================================*/ @@ -333,7 +339,25 @@ /* Initialize the dev_link_t structure */ link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); + + if (!link) + return NULL; + + /* Allocate space for private device-specific data */ + dev = kmalloc(sizeof(struct net_device), GFP_KERNEL); + + if (!dev) + goto fail_alloc_dev; + + local = kmalloc(sizeof(ray_dev_t), GFP_KERNEL); + + if (!local) + goto fail_alloc_local; + memset(link, 0, sizeof(struct dev_link_t)); + memset(dev, 0, sizeof(struct net_device)); + memset(local, 0, sizeof(ray_dev_t)); + link->release.function = &ray_release; link->release.data = (u_long)link; @@ -355,14 +379,9 @@ link->conf.ConfigIndex = 1; link->conf.Present = PRESENT_OPTION; - /* Allocate space for private device-specific data */ - dev = kmalloc(sizeof(struct net_device), GFP_KERNEL); - memset(dev, 0, sizeof(struct net_device)); link->priv = dev; link->irq.Instance = dev; - local = kmalloc(sizeof(ray_dev_t), GFP_KERNEL); - memset(local, 0, sizeof(ray_dev_t)); dev->priv = local; local->finder = link; link->dev = &local->node; @@ -385,7 +404,6 @@ DEBUG(2,"ray_cs ray_attach calling ether_setup.)\n"); ether_setup(dev); - strcpy(dev->name, local->node.dev_name); dev->init = &ray_dev_init; dev->open = &ray_open; dev->stop = &ray_dev_close; @@ -417,6 +435,12 @@ } DEBUG(2,"ray_cs ray_attach ending\n"); return link; + +fail_alloc_local: + kfree(dev); +fail_alloc_dev: + kfree(link); + return NULL; } /* ray_attach */ /*============================================================================= This deletes a driver "instance". The device is de-registered @@ -581,6 +605,8 @@ return; } + strcpy(local->node.dev_name, dev->name); + link->state &= ~DEV_CONFIG_PENDING; printk(KERN_INFO "%s: RayLink, irq %d, hw_addr ", dev->name, dev->irq); @@ -2663,7 +2689,7 @@ } /* End build_auth_frame */ /*===========================================================================*/ - +#ifdef CONFIG_PROC_FS static void raycs_write(const char *name, write_proc_t *w, void *data) { struct proc_dir_entry * entry = create_proc_entry(name, S_IFREG | S_IWUSR, NULL); @@ -2713,6 +2739,7 @@ *(int *)data = nr; return count; } +#endif static int __init init_ray_cs(void) { @@ -2722,12 +2749,14 @@ rc = register_pcmcia_driver(&dev_info, &ray_attach, &ray_detach); DEBUG(1, "raylink init_module register_pcmcia_driver returns 0x%x\n",rc); +#ifdef CONFIG_PROC_FS proc_mkdir("driver/ray_cs", 0); - create_proc_info_entry("driver/ray_cs/ray_cs", 0, NULL, ray_cs_proc_read); + create_proc_info_entry("driver/ray_cs/ray_cs", 0, NULL, &ray_cs_proc_read); raycs_write("driver/ray_cs/essid", write_essid, NULL); raycs_write("driver/ray_cs/net_type", write_int, &net_type); raycs_write("driver/ray_cs/translate", write_int, &translate); +#endif if (translate != 0) translate = 1; return 0; } /* init_ray_cs */ @@ -2739,17 +2768,22 @@ DEBUG(0, "ray_cs: cleanup_module\n"); +#ifdef CONFIG_PROC_FS remove_proc_entry("ray_cs", proc_root_driver); +#endif + unregister_pcmcia_driver(&dev_info); while (dev_list != NULL) { if (dev_list->state & DEV_CONFIG) ray_release((u_long)dev_list); ray_detach(dev_list); } +#ifdef CONFIG_PROC_FS remove_proc_entry("driver/ray_cs/ray_cs", NULL); remove_proc_entry("driver/ray_cs/essid", NULL); remove_proc_entry("driver/ray_cs/net_type", NULL); remove_proc_entry("driver/ray_cs/translate", NULL); remove_proc_entry("driver/ray_cs", NULL); +#endif } /* exit_ray_cs */ module_init(init_ray_cs); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/pppoe.c linux/drivers/net/pppoe.c --- v2.4.0-test5/linux/drivers/net/pppoe.c Mon Jul 10 16:47:23 2000 +++ linux/drivers/net/pppoe.c Wed Aug 9 13:51:09 2000 @@ -5,9 +5,17 @@ * PPPoE --- PPP over Ethernet (RFC 2516) * * - * Version: 0.5.1 + * Version: 0.6.1 * - * 030700 : Fixed connect logic to allow for disconnect + * 030700 : Fixed connect logic to allow for disconnect. + * 270700 : Fixed potential SMP problems; we must protect against + * simultaneous invocation of ppp_input + * and ppp_unregister_channel. + * 040800 : Respect reference count mechanisms on net-devices. + * + * Module reference count is decremented in the right spot now, + * guards against sock_put not actually freeing the sk + * in pppoe_release. * * Author: Michal Ostrowski * @@ -162,36 +170,6 @@ return ret; } -static struct pppox_opt *__find_on_dev(struct net_device *dev, - struct pppox_opt *start) -{ - struct pppox_opt *po; - int hash; - - if (start != NULL) { - hash = hash_item(start->pppoe_pa.sid, start->pppoe_pa.remote); - po = start; - } else { - hash = 0; - po = NULL; - - while (!po && ++hash < PPPOE_HASH_SIZE) - po = item_hash_table[hash]; - } - - while (po && (po->pppoe_dev != dev)){ - if (po->next) { - po = po->next; - } else { - po = NULL; - while (!po && ++hash < PPPOE_HASH_SIZE) - po = item_hash_table[hash]; - } - } - - return po; -} - /********************************************************************** * * Set/get/delete/rehash items @@ -204,6 +182,8 @@ read_lock_bh(&pppoe_hash_lock); po = __get_item(sid, addr); + if(po) + sock_hold(po->sk); read_unlock_bh(&pppoe_hash_lock); return po; @@ -239,20 +219,12 @@ return ret; } -static struct pppox_opt *find_on_dev(struct net_device *dev, - struct pppox_opt *start) -{ - struct pppox_opt *po; - read_lock_bh(&pppoe_hash_lock); - po = __find_on_dev(dev,start); - read_unlock_bh(&pppoe_hash_lock); - return po; -} + /*************************************************************************** * - * Handler for device events - * Certain device events require that sockets be unconnected + * Handler for device events. + * Certain device events require that sockets be unconnected. * **************************************************************************/ static int pppoe_device_event(struct notifier_block *this, @@ -261,6 +233,7 @@ int error = NOTIFY_DONE; struct net_device *dev = (struct net_device *) ptr; struct pppox_opt *po = NULL; + int hash = 0; /* Only look at sockets that are using this specific device. */ switch (event) { @@ -270,26 +243,40 @@ */ case NETDEV_GOING_DOWN: case NETDEV_DOWN: - do { - po = find_on_dev(dev, po); - if(!po) - break; - if (po->sk->state & PPPOX_CONNECTED) - pppox_unbind_sock(po->sk); + /* Find every socket on this device and kill it. */ + read_lock_bh(&pppoe_hash_lock); - if (po->sk->state & PPPOX_CONNECTED) { + while (!po && hash < PPPOE_HASH_SIZE){ + po = item_hash_table[hash]; + ++hash; + } + + while (po && hash < PPPOE_HASH_SIZE){ + if(po->pppoe_dev == dev){ lock_sock(po->sk); - po->sk->shutdown = RCV_SHUTDOWN&SEND_SHUTDOWN; + if (po->sk->state & (PPPOX_CONNECTED|PPPOX_BOUND)){ + pppox_unbind_sock(po->sk); - po->sk->state = PPPOX_DEAD; - po->pppoe_dev = NULL; + dev_put(po->pppoe_dev); + po->pppoe_dev = NULL; - wake_up(po->sk->sleep); - release_sock(po->sk); + po->sk->state = PPPOX_DEAD; + po->sk->state_change(po->sk); + } + release_sock(po->sk); } - } while (1); - + if (po->next) { + po = po->next; + } else { + po = NULL; + while (!po && hash < PPPOE_HASH_SIZE){ + po = item_hash_table[hash]; + ++hash; + } + } + } + read_unlock_bh(&pppoe_hash_lock); break; default: break; @@ -310,60 +297,102 @@ /************************************************************************ * - * Receive a PPPoE Session frame. + * Do the real work of receiving a PPPoE Session frame. * ***********************************************************************/ -static int pppoe_rcv(struct sk_buff *skb, - struct net_device *dev, - struct packet_type *pt) - -{ - struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw; - struct pppox_opt *po; - struct sock *sk ; - - po = get_item((unsigned long) ph->sid, skb->mac.ethernet->h_source); - - if(!po) - goto abort; - - sk = po->sk; - - if (!sk || !(sk->state & PPPOX_CONNECTED)) - goto abort; +int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb){ + struct pppox_opt *po=sk->protinfo.pppox; + struct pppox_opt *relay_po = NULL; if (sk->state & PPPOX_BOUND) { skb_pull(skb, sizeof(struct pppoe_hdr)); - + ppp_input(&po->chan, skb); } else if( sk->state & PPPOX_RELAY ){ - struct pppox_opt *relay_po; relay_po = get_item_by_addr( &po->pppoe_relay ); if( relay_po == NULL || - !( relay_po->sk->state & PPPOX_CONNECTED ) ) + !( relay_po->sk->state & PPPOX_CONNECTED ) ){ goto abort; - + } + skb_pull(skb, sizeof(struct pppoe_hdr)); - if( !__pppoe_xmit( relay_po->sk , skb) ) + if( !__pppoe_xmit( relay_po->sk , skb) ){ goto abort; - + } } else { sock_queue_rcv_skb(sk, skb); } - return 1; - abort: - kfree_skb(skb); + if(relay_po) + sock_put(relay_po->sk); return 0; + } + + + +/************************************************************************ + * + * Receive wrapper called in BH context. + * + ***********************************************************************/ +static int pppoe_rcv(struct sk_buff *skb, + struct net_device *dev, + struct packet_type *pt) + +{ + struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw; + struct pppox_opt *po; + struct sock *sk ; + int ret; + + po = get_item((unsigned long) ph->sid, skb->mac.ethernet->h_source); + + if(!po){ + kfree(skb); + return 0; + } + + sk = po->sk; + bh_lock_sock(sk); + + /* Socket state is unknown, must put skb into backlog. */ + if( sk->lock.users != 0 ){ + sk_add_backlog( sk, skb); + ret = 1; + }else{ + ret = pppoe_rcv_core(sk, skb); + } + + bh_unlock_sock(sk); + sock_put(sk); + return ret; +} + + +/************************************************************************ + * + * Receive wrapper called in process context. + * + ***********************************************************************/ +int pppoe_backlog_rcv(struct sock *sk, struct sk_buff *skb) +{ + lock_sock(sk); + pppoe_rcv_core(sk, skb); + release_sock(sk); + return 0; +} + + + /************************************************************************ * * Receive a PPPoE Discovery frame. - * -- This is solely for detection of PADT frames + * This is solely for detection of PADT frames * ***********************************************************************/ static int pppoe_disc_rcv(struct sk_buff *skb, @@ -373,7 +402,7 @@ { struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw; struct pppox_opt *po; - struct sock *sk ; + struct sock *sk = NULL; if (ph->code != PADT_CODE) goto abort; @@ -381,13 +410,15 @@ po = get_item((unsigned long) ph->sid, skb->mac.ethernet->h_source); if (!po) - goto abort; + goto abort_put; sk = po->sk; pppox_unbind_sock(sk); -abort: + abort_put: + sock_put(sk); + abort: kfree_skb(skb); return 0; } @@ -411,34 +442,18 @@ NULL }; -/********************************************************************** +/*********************************************************************** * - * The destruct hook --- this can be trashed if there is no need for - * the sock to clear its receive queue? + * Really kill the socket. (Called from sock_put if refcnt == 0.) * - *********************************************************************/ -void sock_pppoe_destruct(struct sock *sk) + **********************************************************************/ +void pppoe_sock_destruct(struct sock *sk) { if (sk->protinfo.destruct_hook) kfree(sk->protinfo.destruct_hook); - - while (skb_queue_len(&sk->receive_queue) > 0) { - struct sk_buff *skb = skb_dequeue(&sk->receive_queue); - if (skb) - kfree_skb(skb); - } + MOD_DEC_USE_COUNT; } -int pppoe_backlog_rcv(struct sock *sk, struct sk_buff *skb) -{ - /* Never seen this called, don't expect it to be called, - though I've curious whether or not it ever will be. */ - DEBUG(KERN_CRIT "Backlog rcv called: %p\n", sk); - - kfree_skb(skb); - - return 0; -} /*********************************************************************** * @@ -469,6 +484,7 @@ sk->pprev = NULL; sk->state = PPPOX_NONE; sk->type = SOCK_STREAM; + sk->destruct = pppoe_sock_destruct; sk->protinfo.pppox = kmalloc(sizeof(struct pppox_opt), GFP_KERNEL); if (!sk->protinfo.pppox) { @@ -487,7 +503,6 @@ free_sk: sk_free(sk); - MOD_DEC_USE_COUNT; return error; } @@ -505,27 +520,24 @@ pppox_unbind_sock(sk); - sock_orphan(sk); - /* Signal the death of the socket. */ sk->state = PPPOX_DEAD; po = sk->protinfo.pppox; if (po->pppoe_pa.sid) delete_item(po->pppoe_pa.sid, po->pppoe_pa.remote); - - kfree(po); - + + if (po->pppoe_dev) + dev_put(po->pppoe_dev); /* Should also do a queue purge here */ - sk->protinfo.pppox = NULL; + sock_orphan(sk); sock->sk = NULL; skb_queue_purge(&sk->receive_queue); sock_put(sk); - MOD_DEC_USE_COUNT; return error; } @@ -546,14 +558,15 @@ if (sp->sa_protocol != PX_PROTO_OE) goto end; + /* Check for already bound sockets */ error = -EBUSY; if ((sk->state & PPPOX_CONNECTED) && sp->sa_addr.pppoe.sid) goto end; - dev = dev_get_by_name(sp->sa_addr.pppoe.dev); - - error = -ENODEV; - if (!dev) + /* Check for already disconnected sockets, + on attempts to disconnect */ + error = -EALREADY; + if((sk->state & PPPOX_DEAD) && !sp->sa_addr.pppoe.sid ) goto end; error = 0; @@ -563,6 +576,8 @@ /* Delete the old binding */ delete_item(po->pppoe_pa.sid,po->pppoe_pa.remote); + dev_put(po->pppoe_dev); + memset(po, 0, sizeof(struct pppox_opt)); po->sk = sk; @@ -571,6 +586,14 @@ /* Don't re-bind if sid==0 */ if (sp->sa_addr.pppoe.sid != 0) { + dev = dev_get_by_name(sp->sa_addr.pppoe.dev); + + error = -ENODEV; + if (!dev) + goto end; + + if( ! (dev->flags & IFF_UP) ) + goto end; memcpy(&po->pppoe_pa, &sp->sa_addr.pppoe, sizeof(struct pppoe_addr)); @@ -743,6 +766,8 @@ hdr.code = 0; hdr.sid = sk->num; + lock_sock(sk); + dev = sk->protinfo.pppox->pppoe_dev; skb = sock_wmalloc(sk, total_len + dev->hard_header_len + 32, @@ -755,14 +780,19 @@ /* Reserve space for headers. */ skb_reserve(skb, dev->hard_header_len); skb->nh.raw = skb->data; - skb->dev = dev; + + skb->rx_dev = skb->dev = dev; + dev_hold(skb->rx_dev); + skb->priority = sk->priority; skb->protocol = __constant_htons(ETH_P_PPP_SES); ph = (struct pppoe_hdr *) skb_put(skb, total_len + sizeof(struct pppoe_hdr)); start = (char *) &ph->tag[0]; - copied = memcpy_fromiovec( start, m->msg_iov, m->msg_iovlen); + error = copied = memcpy_fromiovec( start, m->msg_iov, m->msg_iovlen); + if( error <= 0 ) + goto end; dev->hard_header(skb, dev, ETH_P_PPP_SES, sk->protinfo.pppox->pppoe_pa.remote, @@ -773,9 +803,9 @@ ph->length = htons(copied); dev_queue_xmit(skb); - return copied; end: + release_sock(sk); return error; } @@ -830,7 +860,12 @@ skb->protocol = __constant_htons(ETH_P_PPP_SES); skb->nh.raw = skb->data; - skb->dev = dev; + + /* Change device of skb, update reference counts */ + if(skb->rx_dev) + dev_put(skb->rx_dev); + skb->rx_dev = skb->dev = dev; + dev_hold(skb->rx_dev); dev->hard_header(skb, dev, ETH_P_PPP_SES, sk->protinfo.pppox->pppoe_pa.remote, diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/sis900.c linux/drivers/net/sis900.c --- v2.4.0-test5/linux/drivers/net/sis900.c Fri Jul 14 12:12:11 2000 +++ linux/drivers/net/sis900.c Wed Aug 9 14:24:09 2000 @@ -1,8 +1,8 @@ /* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux. Copyright 1999 Silicon Integrated System Corporation - Revision: 1.07 Mar. 07 2000 - - Modified from the driver which is originally written by Donald Becker. + Revision: 1.07.01 Aug. 08 2000 + + Modified from the driver which is originally written by Donald Becker. This software may be used and distributed according to the terms of the GNU Public License (GPL), incorporated herein by reference. @@ -18,13 +18,14 @@ preliminary Rev. 1.0 Jan. 18, 1998 http://www.sis.com.tw/support/databook.htm + Rev 1.07.01 Aug. 08 2000 Ollie Lho minor update fro SiS 630E and SiS 630E A1 Rev 1.07 Mar. 07 2000 Ollie Lho bug fix in Rx buffer ring Rev 1.06.04 Feb. 11 2000 Jeff Garzik softnet and init for kernel 2.4 Rev 1.06.03 Dec. 23 1999 Ollie Lho Third release - Rev 1.06.02 Nov. 23 1999 Ollie Lho bug in mac probing fixed + Rev 1.06.02 Nov. 23 1999 Ollie Lho bug in mac probing fixed Rev 1.06.01 Nov. 16 1999 Ollie Lho CRC calculation provide by Joseph Zbiciak (im14u2c@primenet.com) Rev 1.06 Nov. 4 1999 Ollie Lho (ollie@sis.com.tw) Second release - Rev 1.05.05 Oct. 29 1999 Ollie Lho (ollie@sis.com.tw) Single buffer Tx/Rx + Rev 1.05.05 Oct. 29 1999 Ollie Lho (ollie@sis.com.tw) Single buffer Tx/Rx Chin-Shan Li (lcs@sis.com.tw) Added AMD Am79c901 HomePNA PHY support Rev 1.05 Aug. 7 1999 Jim Huang (cmhuang@sis.com.tw) Initial release */ @@ -53,7 +54,7 @@ #include "sis900.h" static const char *version = -"sis900.c: v1.07 03/07/2000\n"; +"sis900.c: v1.07.01 08/08/2000\n"; static int max_interrupt_work = 20; static int multicast_filter_limit = 128; @@ -109,23 +110,23 @@ }; typedef struct _BufferDesc { - u32 link; - u32 cmdsts; - u32 bufptr; + u32 link; + u32 cmdsts; + u32 bufptr; } BufferDesc; struct sis900_private { struct net_device_stats stats; struct pci_dev * pci_dev; - + spinlock_t lock; struct mii_phy * mii; unsigned int cur_phy; - struct timer_list timer; /* Link status detection timer. */ + struct timer_list timer; /* Link status detection timer. */ - unsigned int cur_rx, dirty_rx; + unsigned int cur_rx, dirty_rx; /* producer/comsumer pointers for Tx/Rx ring */ unsigned int cur_tx, dirty_tx; /* The saved address of a sent/receive-in-place packet buffer */ @@ -196,32 +197,102 @@ return 0; } -static struct net_device * __init sis900_mac_probe (struct pci_dev * pci_dev, char * card_name) +/* older SiS900 and friends, use EEPROM to store MAC address */ +static int sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev) { - struct sis900_private *sis_priv; long ioaddr = pci_resource_start(pci_dev, 0); - struct net_device *net_dev = NULL; - int irq = pci_dev->irq; u16 signature; int i; - if ((net_dev = init_etherdev(net_dev, 0)) == NULL) - return NULL; - /* check to see if we have sane EEPROM */ signature = (u16) read_eeprom(ioaddr, EEPROMSignature); if (signature == 0xffff || signature == 0x0000) { printk (KERN_INFO "%s: Error EERPOM read %x\n", net_dev->name, signature); + return 0; + } + + /* get MAC address from EEPROM */ + for (i = 0; i < 3; i++) + ((u16 *)(net_dev->dev_addr))[i] = read_eeprom(ioaddr, i+EEPROMMACAddr); + + return 1; +} + +/* SiS630E model, use APC CMOS RAM to store MAC address */ +static int sis630e_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev) +{ + struct pci_dev *isa_bridge = NULL; + u8 reg; + int i; + + if ((isa_bridge = pci_find_device(0x1039, 0x0008, isa_bridge)) == NULL) { + printk("%s: Can not find ISA bridge\n", net_dev->name); + return 0; + } + pci_read_config_byte(isa_bridge, 0x48, ®); + pci_write_config_byte(isa_bridge, 0x48, reg | 0x40); + + for (i = 0; i < 6; i++) { + outb(0x09 + i, 0x70); + ((u8 *)(net_dev->dev_addr))[i] = inb(0x71); + } + pci_write_config_byte(isa_bridge, 0x48, reg & ~0x40); + + return 1; +} + +/* SiS630E A1, The Mac address is hardcoded in the RFCR register so it is actually not necessary to + probe the MAC address */ +static int sis630ea1_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev) +{ + long ioaddr = pci_resource_start(pci_dev, 0); + u32 reg; + int i; + + /* reload MAC address */ + reg = inl(ioaddr + cr); + outl(reg | RELOAD, ioaddr + cr); + + reg = inl(ioaddr + cr); + outl(reg & ~RELOAD, ioaddr + cr); + + for (i = 0; i < 3; i++) { + outl((u32)(0x00000004+i) << RFADDR_shift, ioaddr + rfcr); + ((u16 *)(net_dev->dev_addr))[i] = inl(ioaddr + rfdr); + } + + return 1; +} + +static struct net_device * __init sis900_mac_probe (struct pci_dev * pci_dev, char * card_name) +{ + struct sis900_private *sis_priv; + long ioaddr = pci_resource_start(pci_dev, 0); + struct net_device *net_dev = NULL; + int irq = pci_dev->irq; + int i, ret = 0; + u8 revision; + + if ((net_dev = init_etherdev(net_dev, 0)) == NULL) + return NULL; + + pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision); + if (revision == SIS630E_REV) + ret = sis630e_get_mac_addr(pci_dev, net_dev); + else if (revision == SIS630EA1_REV) + ret = sis630ea1_get_mac_addr(pci_dev, net_dev); + else + ret = sis900_get_mac_addr(pci_dev, net_dev); + + if (ret == 0) { + unregister_netdevice(net_dev); return NULL; } + /* print some information about our NIC */ printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ", net_dev->name, card_name, ioaddr, irq); - - /* get MAC address from EEPROM */ - for (i = 0; i < 3; i++) - ((u16 *)(net_dev->dev_addr))[i] = read_eeprom(ioaddr, i+EEPROMMACAddr); for (i = 0; i < 5; i++) printk("%2.2x:", (u8)net_dev->dev_addr[i]); printk("%2.2x.\n", net_dev->dev_addr[i]); @@ -269,58 +340,69 @@ { struct sis900_private * sis_priv = (struct sis900_private *)net_dev->priv; int phy_addr; - + u8 revision; + sis_priv->mii = NULL; - + /* search for total of 32 possible mii phy addresses */ for (phy_addr = 0; phy_addr < 32; phy_addr++) { u16 mii_status; u16 phy_id0, phy_id1; int i; - + mii_status = mdio_read(net_dev, phy_addr, MII_STATUS); if (mii_status == 0xffff || mii_status == 0x0000) /* the mii is not accessable, try next one */ continue; - + phy_id0 = mdio_read(net_dev, phy_addr, MII_PHY_ID0); phy_id1 = mdio_read(net_dev, phy_addr, MII_PHY_ID1); - + /* search our mii table for the current mii */ for (i = 0; mii_chip_table[i].phy_id1; i++) if (phy_id0 == mii_chip_table[i].phy_id0) { struct mii_phy * mii_phy; - - printk(KERN_INFO + + printk(KERN_INFO "%s: %s transceiver found at address %d.\n", - net_dev->name, mii_chip_table[i].name, + net_dev->name, mii_chip_table[i].name, phy_addr);; if ((mii_phy = kmalloc(sizeof(struct mii_phy), GFP_KERNEL)) != NULL) { mii_phy->chip_info = mii_chip_table+i; mii_phy->phy_addr = phy_addr; - mii_phy->status = mdio_read(net_dev, phy_addr, + mii_phy->status = mdio_read(net_dev, phy_addr, MII_STATUS); mii_phy->next = sis_priv->mii; sis_priv->mii = mii_phy; } - /* the current mii is on our mii_info_table, + /* the current mii is on our mii_info_table, try next address */ break; } } - + if (sis_priv->mii == NULL) { - printk(KERN_INFO "%s: No MII transceivers found!\n", + printk(KERN_INFO "%s: No MII transceivers found!\n", net_dev->name); return 0; } - /* arbitrary choose that last PHY and current PHY */ + /* arbitrary choose that last PHY as current PHY */ sis_priv->cur_phy = sis_priv->mii->phy_addr; printk(KERN_INFO "%s: Using %s as default\n", net_dev->name, sis_priv->mii->chip_info->name); - if (sis_priv->mii->status & MII_STAT_LINK) + pci_read_config_byte(sis_priv->pci_dev, PCI_CLASS_REVISION, &revision); + if (revision == SIS630E_REV) { + /* SiS 630E has some bugs on default value of PHY registers */ + mdio_write(net_dev, sis_priv->cur_phy, MII_ANADV, 0x05e1); + mdio_write(net_dev, sis_priv->cur_phy, MII_CONFIG1, 0x22); + mdio_write(net_dev, sis_priv->cur_phy, MII_CONFIG2, 0xff00); + mdio_write(net_dev, sis_priv->cur_phy, MII_MASK, 0xffc0); + mdio_write(net_dev, sis_priv->cur_phy, MII_CONTROL, 0x1000); + } + + if (sis_priv->mii->status & MII_STAT_LINK) sis_priv->LinkOn = TRUE; else sis_priv->LinkOn = FALSE; @@ -365,7 +447,7 @@ retval = (retval << 1) | ((inl(ee_addr) & EEDO) ? 1 : 0); eeprom_delay(); } - + /* Terminate the EEPROM access. */ outl(0, ee_addr); eeprom_delay(); @@ -426,6 +508,8 @@ outl(MDC, mdio_addr); mdio_delay(); } + outl(0x00, mdio_addr); + return retval; } @@ -454,10 +538,10 @@ outl(dataval, mdio_addr); mdio_delay(); outl(dataval | MDC, mdio_addr); - mdio_delay(); + mdio_delay(); } mdio_delay(); - + /* Clear out extra bits. */ for (i = 2; i > 0; i--) { outb(0, mdio_addr); @@ -465,6 +549,8 @@ outb(MDC, mdio_addr); mdio_delay(); } + outl(0x00, mdio_addr); + return; } @@ -518,7 +604,7 @@ long ioaddr = net_dev->base_addr; u32 rfcrSave; u32 i; - + rfcrSave = inl(rfcr + ioaddr); /* disable packet filtering before setting filter */ @@ -547,12 +633,12 @@ sis900_init_tx_ring(struct net_device *net_dev) { struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv; - long ioaddr = net_dev->base_addr; + long ioaddr = net_dev->base_addr; int i; - + sis_priv->tx_full = 0; sis_priv->dirty_tx = sis_priv->cur_tx = 0; - + for (i = 0; i < NUM_TX_DESC; i++) { sis_priv->tx_skbuff[i] = NULL; @@ -563,21 +649,21 @@ sis_priv->tx_ring[i-1].link = (u32) virt_to_bus(&sis_priv->tx_ring[0]); /* load Transmit Descriptor Register */ - outl(virt_to_bus(&sis_priv->tx_ring[0]), ioaddr + txdp); + outl(virt_to_bus(&sis_priv->tx_ring[0]), ioaddr + txdp); if (sis900_debug > 2) - printk(KERN_INFO "%s: TX descriptor register loaded with: %8.8x\n", + printk(KERN_INFO "%s: TX descriptor register loaded with: %8.8x\n", net_dev->name, inl(ioaddr + txdp)); } -/* Initialize the Rx descriptor ring, pre-allocate recevie buffers */ +/* Initialize the Rx descriptor ring, pre-allocate recevie buffers */ static void -sis900_init_rx_ring(struct net_device *net_dev) -{ - struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv; - long ioaddr = net_dev->base_addr; +sis900_init_rx_ring(struct net_device *net_dev) +{ + struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv; + long ioaddr = net_dev->base_addr; int i; - - sis_priv->cur_rx = 0; + + sis_priv->cur_rx = 0; sis_priv->dirty_rx = 0; /* init RX descriptor */ @@ -596,8 +682,8 @@ if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) { /* not enough memory for skbuff, this makes a "hole" - on the buffer ring, it is not clear how the - hardware will react to this kind of degenerated + on the buffer ring, it is not clear how the + hardware will react to this kind of degenerated buffer */ break; } @@ -611,7 +697,7 @@ /* load Receive Descriptor Register */ outl(virt_to_bus(&sis_priv->rx_ring[0]), ioaddr + rxdp); if (sis900_debug > 2) - printk(KERN_INFO "%s: RX descriptor register loaded with: %8.8x\n", + printk(KERN_INFO "%s: RX descriptor register loaded with: %8.8x\n", net_dev->name, inl(ioaddr + rxdp)); } /* on each timer ticks we check two things, Link Status (ON/OFF) and @@ -626,10 +712,11 @@ u16 status; status = mdio_read(net_dev, sis_priv->cur_phy, MII_STATUS); + status = mdio_read(net_dev, sis_priv->cur_phy, MII_STATUS); /* current mii phy is failed to link, try another one */ - while (!(status & MII_STAT_LINK)) { - if (mii_phy->next == NULL) { + while (!(status & MII_STAT_LINK)) { + if (mii_phy->next == NULL) { if (sis_priv->LinkOn) { /* link stat change from ON to OFF */ next_tick = HZ; @@ -653,11 +740,13 @@ if (mii_phy->phy_addr != sis_priv->cur_phy) { printk(KERN_INFO "%s: Changing transceiver to %s\n", net_dev->name, mii_phy->chip_info->name); + /* disable previous PHY */ status = mdio_read(net_dev, sis_priv->cur_phy, MII_CONTROL); - mdio_write(net_dev, sis_priv->cur_phy, + mdio_write(net_dev, sis_priv->cur_phy, MII_CONTROL, status | MII_CNTL_ISOLATE); + /* enable next PHY */ status = mdio_read(net_dev, mii_phy->phy_addr, MII_CONTROL); - mdio_write(net_dev, mii_phy->phy_addr, + mdio_write(net_dev, mii_phy->phy_addr, MII_CONTROL, status & ~MII_CNTL_ISOLATE); sis_priv->cur_phy = mii_phy->phy_addr; } @@ -700,7 +789,7 @@ { int i = 0; u32 status; - + /* STSOUT register is Latched on Transition, read operation updates it */ while (i++ < 2) status = mdio_read(net_dev, phy_addr, MII_STSOUT); @@ -718,9 +807,9 @@ if (status & MII_STSOUT_LINK_FAIL) printk(KERN_INFO "%s: Media Link Off\n", net_dev->name); else - printk(KERN_INFO "%s: Media Link On %s %s-duplex \n", + printk(KERN_INFO "%s: Media Link On %s %s-duplex \n", net_dev->name, - *speed == HW_SPEED_100_MBPS ? + *speed == HW_SPEED_100_MBPS ? "100mbps" : "10mbps", *duplex == FDX_CAPABLE_FULL_SELECTED ? "full" : "half"); @@ -729,7 +818,7 @@ { int i; u16 status; - + for (i = 0; i < 2; i++) status = mdio_read(net_dev, phy_addr, MII_STATUS); @@ -747,22 +836,21 @@ *duplex = FDX_CAPABLE_HALF_SELECTED; if (status & MII_STSSUM_LINK) - printk(KERN_INFO "%s: Media Link On %s %s-duplex \n", + printk(KERN_INFO "%s: Media Link On %s %s-duplex \n", net_dev->name, - *speed == HW_SPEED_100_MBPS ? + *speed == HW_SPEED_100_MBPS ? "100mbps" : "10mbps", *duplex == FDX_CAPABLE_FULL_SELECTED ? "full" : "half"); else printk(KERN_INFO "%s: Media Link Off\n", net_dev->name); - } else { /* HomePNA */ *speed = HW_SPEED_HOME; *duplex = FDX_CAPABLE_HALF_SELECTED; if (status & MII_STAT_LINK) - printk(KERN_INFO "%s: Media Link On 1mbps half-duplex \n", + printk(KERN_INFO "%s: Media Link On 1mbps half-duplex \n", net_dev->name); else printk(KERN_INFO "%s: Media Link Off\n", net_dev->name); @@ -777,7 +865,7 @@ printk(KERN_INFO "%s: Transmit timeout, status %8.8x %8.8x \n", net_dev->name, inl(ioaddr + cr), inl(ioaddr + isr)); - + /* Disable interrupts by clearing the interrupt mask. */ outl(0x0000, ioaddr + imr); @@ -864,7 +952,7 @@ do { status = inl(ioaddr + isr); - + if ((status & (HIBERR|TxURN|TxERR|TxIDLE|RxORN|RxERR|RxOK)) == 0) /* nothing intresting happened */ break; @@ -891,7 +979,7 @@ break; } } while (1); - + if (sis900_debug > 3) printk(KERN_INFO "%s: exiting interrupt, " "interrupt status = 0x%#8.8x.\n", @@ -909,17 +997,17 @@ long ioaddr = net_dev->base_addr; unsigned int entry = sis_priv->cur_rx % NUM_RX_DESC; u32 rx_status = sis_priv->rx_ring[entry].cmdsts; - + if (sis900_debug > 3) printk(KERN_INFO "sis900_rx, cur_rx:%4.4d, dirty_rx:%4.4d " "status:0x%8.8x\n", sis_priv->cur_rx, sis_priv->dirty_rx, rx_status); - + while (rx_status & OWN) { unsigned int rx_size; - + rx_size = (rx_status & DSIZE) - CRC_SIZE; - + if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) { /* corrupted packet received */ if (sis900_debug > 3) @@ -939,15 +1027,15 @@ sis_priv->rx_ring[entry].cmdsts = RX_BUF_SIZE; } else { struct sk_buff * skb; - + /* This situation should never happen, but due to some unknow bugs, it is possible that - we are working on NULL sk_buff :-( */ + we are working on NULL sk_buff :-( */ if (sis_priv->rx_skbuff[entry] == NULL) { printk(KERN_INFO "%s: NULL pointer " "encountered in Rx ring, skipping\n", net_dev->name); - break; + break; } /* gvie the socket buffer to upper layers */ @@ -990,14 +1078,14 @@ entry = sis_priv->cur_rx % NUM_RX_DESC; rx_status = sis_priv->rx_ring[entry].cmdsts; } // while - + /* refill the Rx buffer, what if the rate of refilling is slower than consuming ?? */ for (;sis_priv->cur_rx - sis_priv->dirty_rx > 0; sis_priv->dirty_rx++) { struct sk_buff *skb; - + entry = sis_priv->dirty_rx % NUM_RX_DESC; - + if (sis_priv->rx_skbuff[entry] == NULL) { if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) { /* not enough memory for skbuff, this makes a "hole" @@ -1018,7 +1106,7 @@ } /* re-enable the potentially idle receive state matchine */ outl(RxENA , ioaddr + cr ); - + return 0; } @@ -1027,21 +1115,21 @@ static void sis900_finish_xmit (struct net_device *net_dev) { struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv; - + for (; sis_priv->dirty_tx < sis_priv->cur_tx; sis_priv->dirty_tx++) { unsigned int entry; u32 tx_status; - + entry = sis_priv->dirty_tx % NUM_TX_DESC; tx_status = sis_priv->tx_ring[entry].cmdsts; - + if (tx_status & OWN) { /* The packet is not transmited yet (owned by hardware) ! Note: the interrupt is generated only when Tx Machine is idle, so this is an almost impossible case */ break; } - + if (tx_status & (ABORT | UNDERRUN | OWCOLL)) { /* packet unsuccessfully transmited */ if (sis900_debug > 3) @@ -1069,8 +1157,8 @@ sis_priv->tx_ring[entry].bufptr = 0; sis_priv->tx_ring[entry].cmdsts = 0; } - - if (sis_priv->tx_full && netif_queue_stopped(net_dev) && + + if (sis_priv->tx_full && netif_queue_stopped(net_dev) && sis_priv->cur_tx - sis_priv->dirty_tx < NUM_TX_DESC - 4) { /* The ring is no longer full, clear tx_full and schedule more transmission by netif_wake_queue(net_dev) */ @@ -1085,7 +1173,7 @@ long ioaddr = net_dev->base_addr; struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv; int i; - + netif_stop_queue(net_dev); /* Disable interrupts by clearing the interrupt mask. */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/sis900.h linux/drivers/net/sis900.h --- v2.4.0-test5/linux/drivers/net/sis900.h Wed Dec 29 13:13:16 1999 +++ linux/drivers/net/sis900.h Wed Aug 9 14:24:09 2000 @@ -25,19 +25,20 @@ ier=0x18, //Interrupt Enable Register epar=0x18, //Enhanced PHY Access Register txdp=0x20, //Transmit Descriptor Pointer Register - txcfg=0x24, //Transmit Configuration Register - rxdp=0x30, //Receive Descriptor Pointer Register - rxcfg=0x34, //Receive Configuration Register - flctrl=0x38, //Flow Control Register - rxlen=0x3c, //Receive Packet Length Register - rfcr=0x48, //Receive Filter Control Register - rfdr=0x4C, //Receive Filter Data Register - pmctrl=0xB0, //Power Management Control Register - pmer=0xB4 //Power Management Wake-up Event Register + txcfg=0x24, //Transmit Configuration Register + rxdp=0x30, //Receive Descriptor Pointer Register + rxcfg=0x34, //Receive Configuration Register + flctrl=0x38, //Flow Control Register + rxlen=0x3c, //Receive Packet Length Register + rfcr=0x48, //Receive Filter Control Register + rfdr=0x4C, //Receive Filter Data Register + pmctrl=0xB0, //Power Management Control Register + pmer=0xB4 //Power Management Wake-up Event Register }; /* Symbolic names for bits in various registers */ enum sis900_command_register_bits { + RELOAD = 0x00000400, RESET = 0x00000100, SWI = 0x00000080, RxRESET = 0x00000020, TxRESET = 0x00000010, RxDIS = 0x00000008, RxENA = 0x00000004, TxDIS = 0x00000002, TxENA = 0x00000001 @@ -214,6 +215,10 @@ enum mii_stssum_register_bits { MII_STSSUM_LINK = 0x0008, MII_STSSUM_DPLX = 0x0004, MII_STSSUM_AUTO = 0x0002, MII_STSSUM_SPD = 0x0001 +}; + +enum sis630_revision_id { + SIS630E_REV = 0x81, SIS630EA1_REV = 0x83 }; #define FDX_CAPABLE_DUPLEX_UNKNOWN 0 diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/sk98lin/Makefile linux/drivers/net/sk98lin/Makefile --- v2.4.0-test5/linux/drivers/net/sk98lin/Makefile Tue Nov 23 22:42:20 1999 +++ linux/drivers/net/sk98lin/Makefile Sun Aug 6 11:23:40 2000 @@ -10,7 +10,6 @@ skxmac2.o skcsum.o else ifeq ($(CONFIG_SK98LIN),m) - MOD_LIST_NAME := SK98LIN_MODULES M_OBJS := sk98lin.o O_TARGET := sk98lin.o O_OBJS = skge.o skaddr.o skgehwt.o skgeinit.o skgepnmi.o skgesirq.o \ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/sk98lin/skge.c linux/drivers/net/sk98lin/skge.c --- v2.4.0-test5/linux/drivers/net/sk98lin/skge.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/net/sk98lin/skge.c Sun Aug 6 22:20:09 2000 @@ -2406,8 +2406,7 @@ SkEventDispatcher(pAC, pAC->IoBase); for (i=0; iGIni.GIMacsFound; i++) { - spin_lock_irqsave( - &pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock, Flags); + spin_lock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock); } netif_stop_queue(pAC->dev); @@ -2500,8 +2499,7 @@ netif_start_queue(pAC->dev); for (i=pAC->GIni.GIMacsFound-1; i>=0; i--) { - spin_unlock_irqrestore( - &pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock, Flags); + spin_unlock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock); } /* enable Interrupts */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/skfp/Makefile linux/drivers/net/skfp/Makefile --- v2.4.0-test5/linux/drivers/net/skfp/Makefile Sun Feb 20 21:12:39 2000 +++ linux/drivers/net/skfp/Makefile Sun Aug 6 11:23:40 2000 @@ -10,7 +10,6 @@ smtparse.o hwt.o drvfbi.o ess.o else ifeq ($(CONFIG_SKFP),m) - MOD_LIST_NAME := SKFP_MODULES M_OBJS := skfp.o O_TARGET := skfp.o O_OBJS = skfddi.o hwmtm.o fplustm.o smt.o cfm.o \ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/slip.c linux/drivers/net/slip.c --- v2.4.0-test5/linux/drivers/net/slip.c Mon Jul 10 16:47:24 2000 +++ linux/drivers/net/slip.c Sun Aug 6 22:20:09 2000 @@ -1260,8 +1260,10 @@ switch(cmd){ case SIOCSKEEPALIVE: /* max for unchar */ - if (((unsigned int)((unsigned long)rq->ifr_data)) > 255) + if (((unsigned int)((unsigned long)rq->ifr_data)) > 255) { + spin_unlock_bh(&sl->lock); return -EINVAL; + } sl->keepalive = (unchar) ((unsigned long)rq->ifr_data); if (sl->keepalive != 0) { sl->keepalive_timer.expires=jiffies+sl->keepalive*HZ; @@ -1270,7 +1272,6 @@ } else { del_timer(&sl->keepalive_timer); } - spin_unlock_bh(&sl->lock); break; case SIOCGKEEPALIVE: @@ -1278,8 +1279,10 @@ break; case SIOCSOUTFILL: - if (((unsigned)((unsigned long)rq->ifr_data)) > 255) /* max for unchar */ + if (((unsigned)((unsigned long)rq->ifr_data)) > 255) { /* max for unchar */ + spin_unlock_bh(&sl->lock); return -EINVAL; + } if ((sl->outfill = (unchar)((unsigned long) rq->ifr_data)) != 0){ mod_timer(&sl->outfill_timer, jiffies+sl->outfill*HZ); set_bit(SLF_OUTWAIT, &sl->flags); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/stnic.c linux/drivers/net/stnic.c --- v2.4.0-test5/linux/drivers/net/stnic.c Thu Jul 27 17:38:00 2000 +++ linux/drivers/net/stnic.c Wed Aug 9 13:59:04 2000 @@ -20,6 +20,7 @@ #include #include #include +#include #include "8390.h" @@ -99,6 +100,10 @@ tmp.base_addr = 0x1000; dev = &tmp; + + /* If we are not running on a SolutionEngine, give up now */ + if (! MACH_SE) + return -ENODEV; if (load_8390_module ("stnic.c")) return -ENOSYS; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/wan/Makefile linux/drivers/net/wan/Makefile --- v2.4.0-test5/linux/drivers/net/wan/Makefile Fri Jul 14 12:12:11 2000 +++ linux/drivers/net/wan/Makefile Sun Aug 6 22:20:09 2000 @@ -76,10 +76,12 @@ ifeq ($(CONFIG_COMX_HW_LOCOMX),y) L_OBJS += comx-hw-locomx.o CONFIG_85230_BUILTIN=y +CONFIG_SYNCPPP_BUILTIN = y else ifeq ($(CONFIG_COMX_HW_LOCOMX),m) M_OBJS += comx-hw-locomx.o CONFIG_85230_MODULE=y + CONFIG_SYNCPPP_MODULE = y endif endif diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/wan/lmc/Makefile linux/drivers/net/wan/lmc/Makefile --- v2.4.0-test5/linux/drivers/net/wan/lmc/Makefile Wed Apr 26 16:34:08 2000 +++ linux/drivers/net/wan/lmc/Makefile Sun Aug 6 11:23:40 2000 @@ -9,7 +9,6 @@ O_OBJS = lmc_debug.o lmc_media.o lmc_main.o lmc_proto.o else ifeq ($(CONFIG_LANMEDIA),m) - MOD_LIST_NAME := NET_MODULES M_OBJS := lmc.o O_TARGET := lmc.o O_OBJS = lmc_debug.o lmc_media.o lmc_main.o lmc_proto.o diff -u --recursive --new-file v2.4.0-test5/linux/drivers/net/wan/syncppp.c linux/drivers/net/wan/syncppp.c --- v2.4.0-test5/linux/drivers/net/wan/syncppp.c Wed Apr 26 16:34:08 2000 +++ linux/drivers/net/wan/syncppp.c Fri Aug 4 18:18:49 2000 @@ -723,7 +723,7 @@ struct in_device *in_dev; struct in_ifaddr *ifa; u32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */ - +#ifdef CONFIG_INET if ((in_dev=in_dev_get(dev)) != NULL) { read_lock(&in_dev->lock); @@ -739,6 +739,7 @@ read_unlock(&in_dev->lock); in_dev_put(in_dev); } +#endif /* I hope both addr and mask are in the net order */ sppp_cisco_send (sp, CISCO_ADDR_REPLY, addr, mask); break; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c --- v2.4.0-test5/linux/drivers/parport/parport_pc.c Fri Jul 14 12:12:12 2000 +++ linux/drivers/parport/parport_pc.c Sun Aug 6 11:24:58 2000 @@ -2111,7 +2111,7 @@ #undef printmode printk("]\n"); if (probedirq != PARPORT_IRQ_NONE) - printk("%s: irq %d detected\n", p->name, probedirq); + printk(KERN_INFO "%s: irq %d detected\n", p->name, probedirq); parport_proc_register(p); request_region (p->base, 3, p->name); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/pci/pci.ids linux/drivers/pci/pci.ids --- v2.4.0-test5/linux/drivers/pci/pci.ids Thu Jul 27 17:38:01 2000 +++ linux/drivers/pci/pci.ids Wed Aug 9 13:49:29 2000 @@ -1910,35 +1910,38 @@ 1105 Sigma Designs, Inc. 8300 REALmagic Hollywood Plus DVD Decoder 1106 VIA Technologies, Inc. + 0305 VT8363/8365 [KT133/KM133] 0391 VT8371 [KX133] - 0501 VT8501 + 0501 VT8501 [Apollo MVP4] 0505 VT82C505 0561 VT82C561 - 0571 VT82C586 IDE [Apollo] + 0571 Bus Master IDE 0576 VT82C576 3V [Apollo Master] 0585 VT82C585VP [Apollo VP1/VPX] 0586 VT82C586/A/B PCI-to-ISA [Apollo VP] 1106 0000 MVP3 ISA Bridge 0595 VT82C595 [Apollo VP2] - 0596 VT82C596 ISA [Apollo PRO] + 0596 VT82C596 ISA [Mobile South] 1106 0000 VT82C596/A/B PCI to ISA Bridge 1458 0596 VT82C596/A/B PCI to ISA Bridge 0597 VT82C597 [Apollo VP3] 0598 VT82C598 [Apollo MVP3] - 0601 VT8601 + 0601 VT8601 [Apollo ProMedia] + 0605 VT8605 [ProSavage PM133] 0680 VT82C680 [Apollo P6] - 0686 VT82C686 [Apollo Super] + 0686 VT82C686 [Apollo Super South] 1106 0000 VT82C686/A PCI to ISA Bridge 1106 0686 VT82C686/A PCI to ISA Bridge - 0691 VT82C691 [Apollo PRO] + 0691 VT82C693A/694x [Apollo PRO133x] 1458 0691 VT82C691 Apollo Pro System Controller + 0698 VT82C693A [Ppollo Pro133 AGP] 0693 VT82C693 [Apollo Pro Plus] 0926 VT82C926 [Amazon] 1000 VT82C570MV 1106 VT82C570MV 1571 VT82C416MV 1595 VT82C595/97 [Apollo VP2/97] - 3038 VT82C586B USB + 3038 UHCI USB 1234 0925 MVP3 USB Controller 3040 VT82C586B ACPI 3043 VT86C100A [Rhine 10/100] @@ -1946,19 +1949,31 @@ 1106 0100 VT86C100A Fast Ethernet Adapter 1186 1400 DFE-530TX 3044 OHCI Compliant IEEE 1394 Host Controller + 3050 VT82C596 Power Management + 3051 VT82C596 Power Management 3057 VT82C686 [Apollo Super ACPI] - 3058 VT82C686 [Apollo Super AC97/Audio] + 3058 AC97 Audio Controller 1462 3091 MS-6309 Onboard Audio - 3068 VT82C686 [Apollo Super AC97/Modem] + 3059 AC97 Audio Controller + 3065 Ethernet Controller + 3068 AC97 Modem Controller + 3074 VT8233 PCI to ISA Bridge + 3091 VT8633 [Apollo Pro266] + 3099 VT8367 [KT266] 5030 VT82C596 ACPI [Apollo PRO] 6100 VT85C100A [Rhine II] 8231 VT8231 [PCI-to-ISA Bridge] - 8391 VT8371 [PCI-PCI Bridge] - 8501 VT8501 + 8235 VT8235 Power Management + 8305 VT8365 [KM133 AGP] + 8391 VT8363/8371 [KT133/KX133 AGP] + 8501 VT8501 [Apollo MVP4 AGP] 8596 VT82C596 [Apollo PRO AGP] 8597 VT82C597 [Apollo VP3 AGP] - 8598 VT82C598 [Apollo MVP3 AGP] - 8601 VT8601 + 8598 VT82C598/694x [Apollo MVP3/Pro133x AGP] + 8601 VT8601 [Apollo ProMedia AGP] + 8605 VT8605 [PM133 AGP] + B091 VT8633 [Apollo Pro266 AGP] + B099 VT8367 [KT266 AGP] 8691 VT82C691 [Apollo Pro] 1107 Stratus Computers 0576 VIA VT82C570MV [Apollo] (Wrong vendor ID!) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/pci/quirks.c linux/drivers/pci/quirks.c --- v2.4.0-test5/linux/drivers/pci/quirks.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/pci/quirks.c Fri Aug 4 11:23:37 2000 @@ -9,7 +9,7 @@ * * The bridge optimization stuff has been removed. If you really * have a silly BIOS which is unable to set your host bridge right, - * use the PowerTweak utility (see http://linux.powertweak.com/). + * use the PowerTweak utility (see http://powertweak.sourceforge.net). */ #include @@ -223,6 +223,18 @@ } /* + * VIA VT82C598 has its device ID settable and many BIOSes + * set it to the ID of VT82C597 for backward compatibility. + * We need to switch it off to be able to recognize the real + * type of the chip. + */ +static void __init quirk_vt82c598_id(struct pci_dev *dev) +{ + pci_write_config_byte(dev, 0xfc, 0); + pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device); +} + +/* * The main table of quirks. */ @@ -232,7 +244,6 @@ /* * Its not totally clear which chipsets are the problematic ones * We know 82C586 and 82C596 variants are affected. - * */ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_isa_dma_hangs }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, quirk_isa_dma_hangs }, @@ -251,6 +262,7 @@ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2, quirk_natoma }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, quirk_nopcipci }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, quirk_nopcipci }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_vt82c598_id }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_vt82c586_acpi }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, quirk_piix4_acpi }, diff -u --recursive --new-file v2.4.0-test5/linux/drivers/pci/setup-res.c linux/drivers/pci/setup-res.c --- v2.4.0-test5/linux/drivers/pci/setup-res.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/pci/setup-res.c Mon Aug 7 14:33:10 2000 @@ -50,45 +50,70 @@ return err; } +/* + * Given the PCI bus a device resides on, try to + * find an acceptable resource allocation for a + * specific device resource.. + */ +static int pci_assign_bus_resource(const struct pci_bus *bus, + struct pci_dev *dev, + struct resource *res, + unsigned long size, + unsigned long min, + unsigned int type_mask) +{ + int i; + + type_mask |= IORESOURCE_IO | IORESOURCE_MEM; + for (i = 0 ; i < 4; i++) { + struct resource *r = bus->resource[i]; + if (!r) + continue; + + /* type_mask must match */ + if ((res->flags ^ r->flags) & type_mask) + continue; + + /* We cannot allocate a non-prefetching resource from a pre-fetching area */ + if ((r->flags & IORESOURCE_PREFETCH) && !(res->flags & IORESOURCE_PREFETCH)) + continue; + + /* Ok, try it out.. */ + if (allocate_resource(r, res, size, min, -1, size, pcibios_align_resource, dev) < 0) + continue; + + /* Update PCI config space. */ + pcibios_update_resource(dev, r, res, i); + return 0; + } + return -EBUSY; +} + int pci_assign_resource(struct pci_dev *dev, int i) { - struct resource *root, *res; + const struct pci_bus *bus = dev->bus; + struct resource *res = dev->resource + i; unsigned long size, min; - res = &dev->resource[i]; + size = res->end - res->start + 1; + min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; - /* Determine the root we allocate from. */ - res->end -= res->start; - res->start = 0; - root = pci_find_parent_resource(dev, res); - if (root == NULL) { - printk(KERN_ERR "PCI: Cannot find parent resource for " - "device %s\n", dev->slot_name); - return -EINVAL; + /* First, try exact prefetching match.. */ + if (pci_assign_bus_resource(bus, dev, res, size, min, IORESOURCE_PREFETCH) < 0) { + /* + * That failed. + * + * But a prefetching area can handle a non-prefetching + * window (it will just not perform as well). + */ + if (!(res->flags & IORESOURCE_PREFETCH) || pci_assign_bus_resource(bus, dev, res, size, min, 0) < 0) { + printk(KERN_ERR "PCI: Failed to allocate resource %d for %s\n", i, dev->name); + return -EBUSY; + } } - min = (res->flags & IORESOURCE_IO ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM); - size = res->end + 1; - DBGC((" for root[%lx:%lx] min[%lx] size[%lx]\n", - root->start, root->end, min, size)); - - if (allocate_resource(root, res, size, min, -1, size, - pcibios_align_resource, dev) < 0) { - printk(KERN_ERR "PCI: Failed to allocate resource %d for %s\n", - i, dev->name); - printk(KERN_ERR " failed root[%lx:%lx] min[%lx] size[%lx]\n", - root->start, root->end, min, size); - printk(KERN_ERR " failed res[%lx:%lx]\n", - res->start, res->end); - return -EBUSY; - } - - DBGC((" got res[%lx:%lx] for resource %d\n", - res->start, res->end, i)); - - /* Update PCI config space. */ - pcibios_update_resource(dev, root, res, i); + DBGC((" got res[%lx:%lx] for resource %d\n", res->start, res->end, i)); return 0; } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/pcmcia/Makefile linux/drivers/pcmcia/Makefile --- v2.4.0-test5/linux/drivers/pcmcia/Makefile Tue Jan 4 13:57:17 2000 +++ linux/drivers/pcmcia/Makefile Sun Aug 6 11:23:40 2000 @@ -12,8 +12,6 @@ MOD_SUB_DIRS := $(SUB_DIRS) ALL_SUB_DIRS := $(SUB_DIRS) -MOD_LIST_NAME := PCMCIA_MODULES - ifeq ($(CONFIG_PCMCIA),y) O_OBJS := cistpl.o rsrc_mgr.o bulkmem.o OX_OBJS := ds.o cs.o @@ -41,8 +39,11 @@ M_OBJS += tcic.o endif ifeq ($(CONFIG_CARDBUS),y) + M_OBJS += yenta_socket.o CORE_OBJS += cardbus.o - MX_OBJS += cb_enabler.o yenta.o pci_socket.o + CARDBUS_OBJS := pci_socket.o yenta.o + OX_OBJS += pci_socket.o yenta.o + MX_OBJS += cb_enabler.o endif endif endif @@ -51,3 +52,6 @@ pcmcia_core.o: $(CORE_OBJS) $(LD) $(LD_RFLAG) -r -o $@ $(CORE_OBJS) + +yenta_socket.o: $(CARDBUS_OBJS) + $(LD) $(LD_RFLAG) -r -o $@ yenta.o pci_socket.o diff -u --recursive --new-file v2.4.0-test5/linux/drivers/pcmcia/cs.c linux/drivers/pcmcia/cs.c --- v2.4.0-test5/linux/drivers/pcmcia/cs.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/pcmcia/cs.c Sat Aug 5 08:39:14 2000 @@ -975,8 +975,10 @@ client = &s->clients; while ((*client) && ((*client) != handle)) client = &(*client)->next; - if (*client == NULL) + if (*client == NULL) { + spin_unlock_irqrestore(&s->lock, flags); return CS_BAD_HANDLE; + } *client = handle->next; handle->client_magic = 0; kfree(handle); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/pcmcia/yenta.c linux/drivers/pcmcia/yenta.c --- v2.4.0-test5/linux/drivers/pcmcia/yenta.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/pcmcia/yenta.c Thu Aug 3 14:10:45 2000 @@ -500,6 +500,7 @@ */ cb_writel(socket, CB_SOCKET_EVENT, -1); cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); + exca_writeb(socket, I365_CSCINT, 0); val = probe_irq_on() & isa_irq_mask; for (i = 1; i < 16; i++) { if (!((val >> i) & 1)) @@ -547,6 +548,7 @@ pci_socket_t * socket = (pci_socket_t *) data; DECLARE_WAITQUEUE(wait, current); + MOD_INC_USE_COUNT; daemonize(); strcpy(current->comm, "CardBus Watcher"); @@ -572,6 +574,7 @@ schedule_timeout(HZ); remove_wait_queue(&socket->wait, &wait); } while (!signal_pending(current)); + MOD_DEC_USE_COUNT; return 0; } @@ -699,7 +702,7 @@ min = PCIBIOS_MIN_MEM; max = ~0U; if (type & IORESOURCE_IO) { align = 1024; - size = 1024; + size = 256; min = PCIBIOS_MIN_IO; max = 0xffff; } @@ -719,6 +722,7 @@ yenta_allocate_res(socket, 0, IORESOURCE_MEM|IORESOURCE_PREFETCH); yenta_allocate_res(socket, 1, IORESOURCE_MEM); yenta_allocate_res(socket, 2, IORESOURCE_IO); + yenta_allocate_res(socket, 3, IORESOURCE_IO); /* PCI isn't clever enough to use this one yet */ } /* diff -u --recursive --new-file v2.4.0-test5/linux/drivers/sbus/char/Makefile linux/drivers/sbus/char/Makefile --- v2.4.0-test5/linux/drivers/sbus/char/Makefile Fri Jan 28 15:09:08 2000 +++ linux/drivers/sbus/char/Makefile Fri Aug 4 18:16:11 2000 @@ -37,6 +37,14 @@ endif endif +ifeq ($(CONFIG_DISPLAY7SEG),y) +O_OBJS += display7seg.o +else + ifeq ($(CONFIG_DISPLAY7SEG),m) + M_OBJS += display7seg.o + endif +endif + endif # eq($(CONFIG_PCI,y) ifeq ($(CONFIG_OBP_FLASH),y) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/sbus/char/display7seg.c linux/drivers/sbus/char/display7seg.c --- v2.4.0-test5/linux/drivers/sbus/char/display7seg.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/sbus/char/display7seg.c Fri Aug 4 18:16:11 2000 @@ -0,0 +1,238 @@ +/* $Id: display7seg.c,v 1.2 2000/08/02 06:22:35 davem Exp $ + * + * display7seg - Driver implementation for the 7-segment display + * present on Sun Microsystems CP1400 and CP1500 + * + * Copyright (c) 2000 Eric Brower (ebrower@usa.net) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include /* request_region, check_region */ +#include /* EBus device */ +#include /* OpenProm Library */ +#include /* put_/get_user_ret */ + +#include + +#define D7S_MINOR 193 +#define D7S_OBPNAME "display7seg" +#define D7S_DEVNAME "d7s" + +static int sol_compat = 0; /* Solaris compatibility mode */ + +#ifdef MODULE +EXPORT_NO_SYMBOLS; + +/* Solaris compatibility flag - + * The Solaris implementation omits support for several + * documented driver features (ref Sun doc 806-0180-03). + * By default, this module supports the documented driver + * abilities, rather than the Solaris implementation: + * + * 1) Device ALWAYS reverts to OBP-specified FLIPPED mode + * upon closure of device or module unload. + * 2) Device ioctls D7SIOCRD/D7SIOCWR honor toggling of + * FLIP bit + * + * If you wish the device to operate as under Solaris, + * omitting above features, set this parameter to non-zero. + */ +MODULE_PARM + (sol_compat, "1i"); +MODULE_PARM_DESC + (sol_compat, + "Disables documented functionality omitted from Solaris driver"); + +MODULE_AUTHOR + ("Eric Brower "); +MODULE_DESCRIPTION + ("7-Segment Display driver for Sun Microsystems CP1400/1500"); +MODULE_SUPPORTED_DEVICE + ("d7s"); +#endif /* ifdef MODULE */ + +/* + * Register block address- see header for details + * ----------------------------------------- + * | DP | ALARM | FLIP | 4 | 3 | 2 | 1 | 0 | + * ----------------------------------------- + * + * DP - Toggles decimal point on/off + * ALARM - Toggles "Alarm" LED green/red + * FLIP - Inverts display for upside-down mounted board + * bits 0-4 - 7-segment display contents + */ +volatile u8* d7s_regs = 0; + +static inline void d7s_free(void) +{ + iounmap(d7s_regs); +} + +static inline int d7s_obpflipped(void) +{ + int opt_node; + + opt_node = prom_getchild(prom_root_node); + opt_node = prom_searchsiblings(opt_node, "options"); + return ((-1 != prom_getintdefault(opt_node, "d7s-flipped?", -1)) ? 0 : 1); +} + +static int d7s_open(struct inode *inode, struct file *f) +{ + if (D7S_MINOR != MINOR(inode->i_rdev)) + return -ENODEV; + + MOD_INC_USE_COUNT; + return 0; +} + +static int d7s_release(struct inode *inode, struct file *f) +{ + if (D7S_MINOR != MINOR(inode->i_rdev)) + return -ENODEV; + + MOD_DEC_USE_COUNT; + + /* Reset flipped state to OBP default only if + * no other users have the device open and we + * are not operating in solaris-compat mode + */ + if (0 == MOD_IN_USE && 0 == sol_compat) { + int regval = 0; + + regval = readb(d7s_regs); + (0 == d7s_obpflipped()) ? + writeb(regval |= D7S_FLIP, d7s_regs): + writeb(regval &= ~D7S_FLIP, d7s_regs); + } + + return 0; +} + +static int d7s_ioctl(struct inode *inode, struct file *f, + unsigned int cmd, unsigned long arg) +{ + __u8 regs = readb(d7s_regs); + __u8 ireg = 0; + + if (D7S_MINOR != MINOR(inode->i_rdev)) + return -ENODEV; + + switch (cmd) { + case D7SIOCWR: + /* assign device register values + * we mask-out D7S_FLIP if in sol_compat mode + */ + get_user_ret(ireg, (int *) arg, -EFAULT); + if (0 != sol_compat) { + (regs & D7S_FLIP) ? + (ireg |= D7S_FLIP) : (ireg &= ~D7S_FLIP); + } + writeb(ireg, d7s_regs); + break; + + case D7SIOCRD: + /* retrieve device register values + * NOTE: Solaris implementation returns D7S_FLIP bit + * as toggled by user, even though it does not honor it. + * This driver will not misinform you about the state + * of your hardware while in sol_compat mode + */ + put_user_ret(regs, (int *) arg, -EFAULT); + break; + + case D7SIOCTM: + /* toggle device mode-- flip display orientation */ + (regs & D7S_FLIP) ? + (regs &= ~D7S_FLIP) : (regs |= D7S_FLIP); + writeb(regs, d7s_regs); + break; + }; + + return 0; +} + +static struct file_operations d7s_fops = { + owner: THIS_MODULE, + ioctl: d7s_ioctl, + open: d7s_open, + release: d7s_release, +}; + +static struct miscdevice d7s_miscdev = { D7S_MINOR, D7S_DEVNAME, &d7s_fops }; + +#ifdef MODULE +int init_module(void) +#else +int __init d7s_init(void) +#endif +{ + struct linux_ebus *ebus = NULL; + struct linux_ebus_device *edev = NULL; + int iTmp = 0, regs = 0; + + for_each_ebus(ebus) { + for_each_ebusdev(edev, ebus) { + if (!strcmp(edev->prom_name, D7S_OBPNAME)) + goto ebus_done; + } + } + +ebus_done: + if(!edev) { + printk("%s: unable to locate device\n", D7S_DEVNAME); + return -ENODEV; + } + + d7s_regs = ioremap(edev->resource[0].start, sizeof(__u8)); + + iTmp = misc_register(&d7s_miscdev); + if (0 != iTmp) { + printk("%s: unable to acquire miscdevice minor %i\n", + D7S_DEVNAME, D7S_MINOR); + return iTmp; + } + + /* OBP option "d7s-flipped?" is honored as default + * for the device, and reset default when detached + */ + regs = readb(d7s_regs); + iTmp = d7s_obpflipped(); + (0 == iTmp) ? + writeb(regs |= D7S_FLIP, d7s_regs): + writeb(regs &= ~D7S_FLIP, d7s_regs); + + printk("%s: 7-Segment Display%s at 0x%lx %s\n", + D7S_DEVNAME, + (0 == iTmp) ? (" (FLIPPED)") : (""), + edev->resource[0].start, + (0 != sol_compat) ? ("in sol_compat mode") : ("")); + + return 0; +} + +#ifdef MODULE +void cleanup_module(void) +{ + int regs = readb(d7s_regs); + + /* Honor OBP d7s-flipped? unless operating in solaris-compat mode */ + if (0 == sol_compat) { + (0 == d7s_obpflipped()) ? + writeb(regs |= D7S_FLIP, d7s_regs): + writeb(regs &= ~D7S_FLIP, d7s_regs); + } + + misc_deregister(&d7s_miscdev); + d7s_free(); +} +#endif diff -u --recursive --new-file v2.4.0-test5/linux/drivers/sbus/char/sunkbd.c linux/drivers/sbus/char/sunkbd.c --- v2.4.0-test5/linux/drivers/sbus/char/sunkbd.c Fri Jul 14 12:12:12 2000 +++ linux/drivers/sbus/char/sunkbd.c Mon Jul 31 19:36:11 2000 @@ -177,9 +177,6 @@ static struct pt_regs * pt_regs; #ifdef CONFIG_MAGIC_SYSRQ -#ifndef CONFIG_PCI -int sysrq_enabled = 1; -#endif unsigned char sun_sysrq_xlate[128] = "\0\0\0\0\0\201\202\212\203\213\204\214\205\0\206\0" /* 0x00 - 0x0f */ "\207\210\211\0\0\0\0\0\0\0\0\0\0\03312" /* 0x10 - 0x1f */ @@ -556,7 +553,7 @@ #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq hack */ if (l1a_state.l1_down) { - if (!up_flag && sysrq_enabled) + if (!up_flag) handle_sysrq(sun_sysrq_xlate[keycode], pt_regs, kbd, tty); goto out; } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/scsi/3w-xxxx.c linux/drivers/scsi/3w-xxxx.c --- v2.4.0-test5/linux/drivers/scsi/3w-xxxx.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/scsi/3w-xxxx.c Fri Aug 4 17:56:25 2000 @@ -62,6 +62,8 @@ 1.02.00.001 - Added support for full command packet posts through ioctls for 3DM. Bug fix so hot spare drives don't show up. + 1.02.00.002 - Fix bug with tw_setfeature() call that caused oops on some + systems. */ #include @@ -107,7 +109,7 @@ }; /* Globals */ -char *tw_driver_version="1.02.00.001"; +char *tw_driver_version="1.02.00.002"; TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT]; int tw_device_extension_count = 0; @@ -747,7 +749,7 @@ kfree(tw_dev); /* Tell the firmware we support shutdown notification*/ - tw_setfeature(tw_dev, 2, 1, &c); + tw_setfeature(tw_dev2, 2, 1, &c); } if (numcards == 0) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/scsi/53c7,8xx.c linux/drivers/scsi/53c7,8xx.c --- v2.4.0-test5/linux/drivers/scsi/53c7,8xx.c Fri Jun 23 21:55:09 2000 +++ linux/drivers/scsi/53c7,8xx.c Tue Aug 8 09:19:25 2000 @@ -5389,9 +5389,10 @@ * to use vverify()? */ - if (MAP_NR(insn) < 1 || MAP_NR(insn + 8) > MAP_NR(high_memory) || + if (virt_to_phys((void *)insn) < PAGE_SIZE || + virt_to_phys((void *)(insn + 8)) > virt_to_phys(high_memory) || ((((dcmd = (insn[0] >> 24) & 0xff) & DCMD_TYPE_MMI) == DCMD_TYPE_MMI) && - MAP_NR(insn + 12) > MAP_NR(high_memory))) { + virt_to_phys((void *)(insn + 12)) > virt_to_phys(high_memory))) { size = 0; sprintf (buf, "%s%p: address out of range\n", prefix, insn); @@ -6381,8 +6382,7 @@ static int check_address (unsigned long addr, int size) { - return (MAP_NR(addr) < 1 || MAP_NR(addr + size) > MAP_NR(high_memory) ? - -1 : 0); + return (virt_to_phys((void *)addr) < PAGE_SIZE || virt_to_phys((void *)(addr + size)) > virt_to_phys(high_memory) ? -1 : 0); } #ifdef MODULE diff -u --recursive --new-file v2.4.0-test5/linux/drivers/scsi/53c7xx.c linux/drivers/scsi/53c7xx.c --- v2.4.0-test5/linux/drivers/scsi/53c7xx.c Fri Jan 28 15:09:08 2000 +++ linux/drivers/scsi/53c7xx.c Tue Aug 8 09:19:25 2000 @@ -5068,9 +5068,10 @@ * to use vverify()? */ - if (MAP_NR(insn) < 1 || MAP_NR(insn + 8) > MAP_NR(high_memory) || + if (virt_to_phys((void *)insn) < PAGE_SIZE || + virt_to_phys((void *)(insn + 8)) > virt_to_phys(high_memory) || ((((dcmd = (insn[0] >> 24) & 0xff) & DCMD_TYPE_MMI) == DCMD_TYPE_MMI) && - MAP_NR(insn + 12) > MAP_NR(high_memory))) { + virt_to_phys((void *)(insn + 12)) > virt_to_phys(high_memory))) { size = 0; sprintf (buf, "%s%p: address out of range\n", prefix, insn); @@ -6052,8 +6053,7 @@ static int check_address (unsigned long addr, int size) { - return (MAP_NR(addr) < 1 || MAP_NR(addr + size) > MAP_NR(high_memory) ? - -1 : 0); + return (virt_to_phys((void *)addr) < PAGE_SIZE || virt_to_phys((void *)(addr + size)) > virt_to_phys(high_memory) ? -1 : 0); } #ifdef MODULE diff -u --recursive --new-file v2.4.0-test5/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile --- v2.4.0-test5/linux/drivers/scsi/Makefile Fri Jun 23 21:55:09 2000 +++ linux/drivers/scsi/Makefile Sun Aug 6 11:23:40 2000 @@ -6,11 +6,10 @@ # O_TARGET := scsidrv.o -MOD_LIST_NAME := SCSI_MODULES SUB_DIRS := MOD_SUB_DIRS := -MOD_IN_SUBDIRS := +MOD_IN_SUB_DIRS := ALL_SUB_DIRS := $(SUB_DIRS) pcmcia ifeq ($(CONFIG_PCMCIA),y) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/scsi/README.ibmmca linux/drivers/scsi/README.ibmmca --- v2.4.0-test5/linux/drivers/scsi/README.ibmmca Mon May 10 13:00:10 1999 +++ linux/drivers/scsi/README.ibmmca Mon Jul 31 11:35:19 2000 @@ -10,10 +10,10 @@ General Public License. Originally written by Martin Kolinek, December 1995. Officially maintained by Michael Lang since January 1999. - Version 3.1e + Version 3.2 - Last update: 20 February 1999 + Last update: 29 July 2000 Authors of this Driver @@ -23,7 +23,8 @@ - Klaus Kudielka (multiple SCSI-host management/detection, adaption to Linux Kernel 2.1.x, module support) - Michael Lang (assigning original pun,lun mapping, dynamical ldn - assignment, this file, patch, official driver maintenance) + assignment, this file, patch, official driver maintenance + and subsequent pains related with the driver :-)) Table of Contents ----------------- @@ -51,7 +52,11 @@ 5.3 Bugreports 5.4 Support WWW-page 6 References - 7 Trademarks + 7 Credits to + 7.1 People + 7.2 Sponsors & Supporters + 8 Trademarks + 9 Disclaimer * * * @@ -64,7 +69,7 @@ quite outdated. The history of the driver development is also kept inside here. Multiple historical developments have been summarized to shorten the textsize a bit. At the end of this file you can find a small manual for - this driver and hints to get it running even on your machine (hopefully). + this driver and hints to get it running on your machine. 2 Driver Description -------------------- @@ -74,27 +79,35 @@ Microchannel-bus support is enabled, as the IBM SCSI-subsystem needs the Microchannel. In a next step, a free interrupt is chosen and the main interrupt handler is connected to it to handle answers of the SCSI- - subsystem(s). In a further step, it is checked, wether there was a forced - detection of the adapter via the kernel commandline, where the I/O port - and the SCSI-subsystem id can be specified. The next step checks if there - is an integrated SCSI-subsystem installed. This register area is fixed - through all IBM PS/2 MCA-machines and appears as something like a virtual - slot 10 of the MCA-bus. If POS-register 2 is not 0xff, there must be a SCSI- + subsystem(s). If the F/W SCSI-adapter is forced by the BIOS to use IRQ11 + instead of IRQ14, IRQ11 is used for the IBM SCSI-2 F/W adapter. In a + further step it is checked, if the adapter gets detected by force from + the kernel commandline, where the I/O port and the SCSI-subsystem id can + be specified. The next step checks if there is an integrated SCSI-subsystem + installed. This register area is fixed through all IBM PS/2 MCA-machines + and appears as something like a virtual slot 10 of the MCA-bus. On most + PS/2 machines, the POS registers of slot 10 are set to 0xff or 0x00 if not + integrated SCSI-controller is available. But on certain PS/2s, like model + 9595, this slot 10 is used to store other information which at earlier + stage confused the driver and resulted in the detection of some ghost-SCSI. + If POS-register 2 and 3 are not 0x00 and not 0xff, but all other POS + registers are either 0xff or 0x00, there must be an integrated SCSI- subsystem present and it will be registered as IBM Integrated SCSI- Subsystem. The next step checks, if there is a slot-adapter installed on the MCA-bus. To get this, the first two POS-registers, that represent the adapter ID are checked. If they fit to one of the ids, stored in the - adapter list, a SCSI-subsystem is assumed to be found and will be + adapter list, a SCSI-subsystem is assumed to be found in a slot and will be registered. This check is done through all possible MCA-bus slots to allow more than one SCSI-adapter to be present in the PS/2-system and this is already the first point of problems. Looking into the technical reference manual for the IBM PS/2 common interfaces, the POS2 register must have - different interpretation of its single bits. While one can assume, that the - integrated subsystem has a fix I/O-address at 0x3540 - 0x3547, further - installed IBM SCSI-adapters must use a different I/O-address. This is - expressed by bit 1 to 3 of POS2 (multiplied by 8 + 0x3540). Bits 2 and 3 - are reserved for the integrated subsystem, but not for the adapters! The - following list shows, how the bits of POS2 and POS3 should be interpreted. + different interpretation of its single bits to avoid overlapping I/O + regions. While one can assume, that the integrated subsystem has a fix + I/O-address at 0x3540 - 0x3547, further installed IBM SCSI-adapters must + use a different I/O-address. This is expressed by bit 1 to 3 of POS2 + (multiplied by 8 + 0x3540). Bits 2 and 3 are reserved for the integrated + subsystem, but not for the adapters! The following list shows, how the + bits of POS2 and POS3 should be interpreted. The POS2-register of all PS/2 models' integrated SCSI-subsystems has the following interpretation of bits: @@ -102,20 +115,25 @@ Bit 3 - 2 : Reserved Bit 1 : 8k NVRAM Disabled Bit 0 : Chip Enable (EN-Signal) - The POS3-register is interpreted as follows (for ALL IBM SCSI-subsys.): + The POS3-register is interpreted as follows (for most IBM SCSI-subsys.): Bit 7 - 5 : SCSI ID Bit 4 - 0 : Reserved = 0 - (taken from "IBM, PS/2 Hardware Interface Technical Reference, Common - Interfaces (1991)"). - In short words, this means, that IBM PS/2 machines only support 1 single - subsystem by default. But (additional) slot-adapters must have another - configuration on pos2 in order to be enabled to use more than one IBM SCSI- - subsystem, e.g. for a network server. From tests with the IBM SCSI Adapter - w/cache, the POS2-register for slot adapters should be interpreted in the - following way: - Bit 7 - 4 : Chip Revision ID (Release) - Bit 3 - 1 : port offset factor ( * 8 + 0x3540 ) - Bit 0 : Chip Enable (EN-Signal) + The slot-adapters have different interpretation of these bits. The IBM SCSI + adapter (w/Cache) and the IBM SCSI-2 F/W adapter use the following + interpretation of the POS2 register: + Bit 7 - 4 : ROM Segment Address Select + Bit 3 - 1 : Adapter I/O Address Select (*8+0x3540) + Bit 0 : Adapter Enable (EN-Signal) + and for the POS3 register: + Bit 7 - 5 : SCSI ID + Bit 4 : Fairness Enable (SCSI ID3 f. F/W) + Bit 3 - 0 : Arbitration Level + The most modern product of the series is the IBM SCSI-2 F/W adapter, it + allows dual-bus SCSI and SCSI-wide addressing, which means, PUNs may be + between 0 and 15. Here, Bit 4 is the high-order bit of the 4-bit wide + adapter PUN expression. In short words, this means, that IBM PS/2 machines + can only support 1 single integrated subsystem by default. Additional + slot-adapters get ports assigned by the automatic configuration tool. One day I found a patch in ibmmca_detect(), forcing the I/O-address to be 0x3540 for integrated SCSI-subsystems, there was a remark placed, that on @@ -156,12 +174,18 @@ number or pun, also called the scsi id, this is the number you select with hardware jumpers), and each physical unit can have up to 8 "logical units" (each identified by logical unit number, or lun, - between 0 and 7). + between 0 and 7). The IBM SCSI-2 F/W adapter offers this on up to two + busses and provides support for 30 logical devices at the same time, where + in wide-addressing mode you can have 16 puns with 32 luns on each device. + This section dexribes you the handling of devices on non-F/W adapters. + Just imagine, that you can have 16 * 32 = 512 devices on a F/W adapter + which means a lot of possible devices for such a small machine. Typically the adapter has pun=7, so puns of other physical units - are between 0 and 6. Almost all physical units have only one - logical unit, with lun=0. A CD-ROM jukebox would be an example of - a physical unit with more than one logical unit. + are between 0 and 6(15). On a wide-adapter a pun higher than 7 is + possible, but is normally not used. Almost all physical units have only + one logical unit, with lun=0. A CD-ROM jukebox would be an example of a + physical unit with more than one logical unit. The embedded microprocessor of the IBM SCSI-subsystem hides the complex two-dimensional (pun,lun) organization from the operating system. @@ -169,7 +193,8 @@ checks, on its own, all 56 possible (pun,lun) combinations, and the first 15 devices found are assigned into a one-dimensional array of so-called "logical devices", identified by "logical device numbers" or ldn. The last - ldn=15 is reserved for the subsystem itself. + ldn=15 is reserved for the subsystem itself. Wide adapters may have + to check up to 15 * 8 = 120 pun/lun combinations. 2.3 SCSI-Device Recognition and dynamical ldn Assignment -------------------------------------------------------- @@ -177,8 +202,12 @@ numbers are also hidden. The two possibilities to get around this problem is to offer fake pun/lun combinations to the operating system or to delete the whole mapping of the adapter and to reassign the ldns, using - the immediate assign command of the SCSI-subsystem. At the beginning of the - development of this driver, the following approach was used: + the immediate assign command of the SCSI-subsystem for probing through + all possible pun/lun combinations. a ldn is a "logical device number" + which is used by IBM SCSI-subsystems to access some valid SCSI-device. + At the beginning of the development of this driver, the following approach + was used: + First, the driver checked the ldn's (0 to 6) to find out which ldn's have devices assigned. This was done by the functions check_devices() and device_exists(). The interrupt handler has a special paragraph of code @@ -199,7 +228,7 @@ and later, realizes the device recognition in the following way: The physical SCSI-devices on the SCSI-bus are probed via immediate_assign- and device_inquiry-commands, that is all implemented in a completely new - made check_devices() subroutine. This delivers a exact map of the physical + made check_devices() subroutine. This delivers an exact map of the physical SCSI-world that is now stored in the get_scsi[][]-array. This means, that the once hidden pun,lun assignment is now known to this driver. It no longer believes in default-settings of the subsystem and maps all @@ -230,7 +259,7 @@ can be different from the old, faked puns. Therefore, Linux will eventually change /dev/sdXXX assignments and prompt you for corrupted superblock repair on boottime. In this case DO NOT PANIC, YOUR DISKS ARE STILL OK!!! - You have to reboot (CTRL-D) with a old kernel and set the /etc/fstab-file + You have to reboot (CTRL-D) with an old kernel and set the /etc/fstab-file entries right. After that, the system should come up as errorfree as before. If your boot-partition is not coming up, also edit the /etc/lilo.conf-file in a Linux session booted on old kernel and run lilo before reboot. Check @@ -332,17 +361,19 @@ ---------------------------------- The following IBM SCSI-subsystems are supported by this driver: - - IBM Fast SCSI-2 Adapter + - IBM Fast/Wide SCSI-2 Adapter - IBM 7568 Industrial Computer SCSI Adapter w/cache - IBM Expansion Unit SCSI Controller - IBM SCSI Adapter w/Cache - IBM SCSI Adapter - IBM Integrated SCSI Controller + - All clones, 100% compatible with the chipset and subsystem command + system of IBM SCSI-adapters (forced detection) 2.14 Linux Kernel Versions -------------------------- The IBM SCSI-subsystem low level driver is prepared to be used with - all versions of Linux between 2.0.x and 2.2.x. The compatibility checks + all versions of Linux between 2.0.x and 2.4.x. The compatibility checks are fully implemented up from version 3.1e of the driver. This means, that you just need the latest ibmmca.h and ibmmca.c file and copy it in the linux/drivers/scsi directory. The code is automatically adapted during @@ -717,18 +748,149 @@ addition more flexibility. - Michael Lang + Apr 23, 2000 (v3.2pre1) + 1) During a very long time, I collected a huge amount of bugreports from + various people, trying really quite different things on their SCSI- + PS/2s. Today, all these bugreports are taken into account and should be + mostly solved. The major topics were: + - Driver crashes during boottime by no obvious reason. + - Driver panics while the midlevel-SCSI-driver is trying to inquire + the SCSI-device properties, even though hardware is in perfect state. + - Displayed info for the various slot-cards is interpreted wrong. + The main reasons for the crashes were two: + 1) The commands to check for device information like INQUIRY, + TEST_UNIT_READY, REQUEST_SENSE and MODE_SENSE cause the devices + to deliver information of up to 255 bytes. Midlevel drivers offer + 1024 bytes of space for the answer, but the IBM-SCSI-adapters do + not accept this, as they stick quite near to ANSI-SCSI and report + a COMMAND_ERROR message which causes the driver to panic. The main + problem was located around the INQUIRY command. Now, for all the + mentioned commands, the buffersize, sent to the adapter is at + maximum 255 which seems to be a quite reasonable solution. + TEST_UNIT_READY gets a buffersize of 0 to make sure, that no + data is transferred in order to avoid any possible command failure. + 2) On unsuccessful TEST_UNIT_READY, the midlevel-driver has to send + a REQUEST_SENSE in order to see, where the problem is located. This + REQUEST_SENSE may have various length in its answer-buffer. IBM + SCSI-subsystems report a command failure, if the returned buffersize + is different from the sent buffersize, but this can be supressed by + a special bit, which is now done and problems seem to be solved. + 2) Code adaption to all kernel-releases. Now, the 3.2 code compiles on + 2.0.x, 2.1.x, 2.2.x and 2.3.x kernel releases without any code-changes. + 3) Commandline-parameters are recognized again, even under Kernel 2.3.x or + higher. + - Michael Lang + + April 27, 2000 (v3.2pre2) + 1) Bypassed commands get read by the adapter by one cycle instead of two. + This increases SCSI-performance. + 2) Synchronous datatransfer is provided for sure to be 5 MHz on older + SCSI and 10 MHz on internal F/W SCSI-adapter. + 3) New commandline parameters allow to force the adapter to slow down while + in synchronous transfer. Could be helpful for very old devices. + - Michael Lang + + June 2, 2000 (v3.2pre5) + 1) Added Jim Shorney's contribution to make the activity indicator + flashing in addition to the LED-alphanumeric display-panel on + models 95A. To be enabled to choose this feature freely, a new + commandline parameter is added, called 'activity'. + 2) Added the READ_CONTROL bit for test_unit_ready SCSI-command. + 3) Added some suppress_exception bits to read_device_capacity and + all device_inquiry occurences in the driver code. + 4) Complaints about the various KERNEL_VERSION implementations are + taken into account. Every local_LinuxKernelVersion occurence is + now replaced by KERNEL_VERSION, defined in linux/version.h. + Corresponding changes were applied to ibmmca.h, too. This was a + contribution to all kernel-parts by Philipp Hahn. + - Michael Lang + + July 17, 2000 (v3.2pre8) + A long period of collecting bugreports from all corners of the world + now lead to the following corrections to the code: + 1) SCSI-2 F/W support crashed with a COMMAND ERROR. The reason for this + was, that it is possible to disbale Fast-SCSI for the external bus. + The feature-control command, where this crash appeared regularly tried + to set the maximum speed of 10MHz synchronous transfer speed and that + reports a COMMAND ERROR, if external bus Fast-SCSI is disabled. Now, + the feature-command probes down from maximum speed until the adapter + stops to complain, which is at the same time the maximum possible + speed selected in the reference program. So, F/W external can run at + 5 MHz (slow-) or 10 MHz (fast-SCSI). During feature probing, the + COMMAND ERROR message is used to detect if the adapter does not complain. + 2) Up to now, only combined busmode is supported, if you use external + SCSI-devices, attached to the F/W-controller. If dual bus is selected, + only the internal SCSI-devices get accessed by Linux. For most + applications, this should do fine. + 3) Wide-SCSI-addressing (16-Bit) is now possible for the internal F/W + bus on the F/W adapter. If F/W adapter is detected, the driver + automatically uses the extended PUN/LUN <-> LDN mapping tables, which + are now new from 3.2pre8. This allows PUNs between 0 and 15 and should + provide more fun with the F/W adapter. + 4) Several machines use the SCSI: POS registers for internal/undocumented + storage of system relevant info. This confused the driver, mainly on + models 9595, as it expected no onboard SCSI only, if all POS in + the integrated SCSI-area are set to 0x00 or 0xff. Now, the mechanism + to check for integrated SCSI is much more restrictive and these problems + should be history. + - Michael Lang + + July 18, 2000 (v3.2pre9) + This develop rather quickly at the moment. Two major things were still + missing in 3.2pre8: + 1) The adapter PUN for F/W adapters has 4-bits, while all other adapters + have 3-bits. This is now taken into account for F/W. + 2) When you select CONFIG_IBMMCA_SCSI_ORDER_STANDARD, you should + normally get the inverse probing order of your devices on the SCSI-bus. + The ANSI device order gets scrambled in version 3.2pre8!! Now, a new + and tested algorithm inverts the device-order on the SCSI-bus and + automatically avoids accidental access to whatever SCSI PUN the adapter + is set and works with SCSI- and Wide-SCSI-addressing. + - Michael Lang + + July 23, 2000 (v3.2pre10 unpublished) + 1) LED panel display supports wide-addressing in ibmmca=display mode. + 2) Adapter-information and autoadaption to address-space is done. + 3) Auto-probing for maximum synchronous SCSI transfer rate is working. + 4) Optimization to some embedded function calls is applied. + 5) Added some comment for the user to wait for SCSI-devices beeing probed. + 6) Finished version 3.2 for Kernel 2.4.0. It least, I thought it is but... + - Michael Lang + + July 26, 2000 (v3.2pre11) + 1) I passed a horrible weekend getting mad with NMIs on kernel 2.2.14 and + a model 9595. Asking around in the community, nobody except of me has + seen such errors. Weired, but I am trying to recompile everything on + the model 9595. Maybe, as I use a specially modified gcc, that could + cause problems. But, it was not the reason. The true background was, + that the kernel was compiled for i386 and the 9595 has a 486DX-2. + Normally, no troubles should appear, but for this special machine, + only the right processor support is working fine! + 2) Previous problems with synchronous speed, slowing down from one adapter + to the next during probing are corrected. Now, local variables store + the synchronous bitmask for every single adapter found on the MCA bus. + 3) LED alphanumeric panel support for XX95 systems is now showing some + alive rotator during boottime. This makes sense, when no monitor is + connected to the system. You can get rid of all display activity, if + you do not use any parameter or just ibmmcascsi=activity, for the + harddrive activity LED, existant on all PS/2, except models 8595-XXX. + If no monitor is available, please use ibmmcascsi=display, which works + fine together with the linuxinfo utility for the LED-panel. + - Michael Lang + + July 29, 2000 (v3.2) + 1) Submission of this driver for kernel 2.4test-XX and 2.2.17. + - Michael Lang + 4 To do ------- + - IBM SCSI-2 F/W external SCSI bus support in seperate mode. - It seems that the handling of bad disks is really bad - non-existent, in fact. - More testing of the full driver-controlled dynamical ldn - (re)mapping for up to 56 SCSI-devices. - - Support more of the SCSI-command set. - - Support some of the caching abilities, particularly Read Prefetch. - This fetches data into the cache, which later gets hit by the - regular Read Data. (<--- This is coming soon!!!!) - - Abort and Reset functions still slightly buggy or better say, - it is the new episode, called SCREAM III. + (re)mapping for up to 56 SCSI-devices. I guess, it won't work + at the moment, but nobody ever really tried it. + - Abort and Reset functions still slightly buggy. 5 Users' Manual --------------- @@ -749,7 +911,13 @@ where '-' stays dark, 'D' shows the SCSI-device id and 'A' shows the SCSI hostindex, beeing currently - accessed. + accessed. During boottime, this will give the message + + SCSIini* + + on the LED-panel, where the * represents a rotator, + showing the activity during the probing phase of the + driver which can take up to two minutes per SCSI-adapter. adisplay This works like display, but gives more optical overview of the activities on the SCSI-bus. The display will have the following output: @@ -761,7 +929,22 @@ hostindex. If display nor adisplay is set, the internal PS/2 harddisk LED is used for media-activities. So, if you really do not have a system with a LED-display, you - should not set display or adisplay. + should not set display or adisplay. Keep in mind, that + display and adisplay can only be used alternatively. It + is not recommended to use this option, if you have some + wide-addressed devices e.g. at the SCSI-2 F/W adapter in + your system. In addition, the usage of the display for + other tasks in parallel, like the linuxinfo-utility makes + no sense with this option. + activity This enables the PS/2 harddisk LED activity indicator. + Most PS/2 have no alphanumeric LED display, but some + indicator. So you should use this parameter to activate it. + If you own model 9595 (Server95), you can have both, the + LED panel and the activity indicator in parallel. However, + some PS/2s, like the 8595 do not have any harddisk LED + activity indicator, which means, that you must use the + alphanumeric LED display if you want to monitor SCSI- + activity. bypass This commandline parameter forces the driver never to use SCSI-subsystems' integrated SCSI-command set. Except of the immediate assign, which is of vital importance for @@ -775,7 +958,10 @@ this flag will slow-down SCSI-accesses slightly, as the software generated commands are always slower than the hardware. Non-harddisk devices always get read/write- - commands in bypass mode. + commands in bypass mode. On the most recent releases of + the Linux IBM-SCSI-driver, the bypass command should be + no longer a necessary thing, if you are sure about your + SCSI-hardware! normal This is the parameter, introduced on the 2.0.x development rail by ZP Gu. This parameter defines the SCSI-device scan order in the new industry standard. This means, that @@ -789,6 +975,19 @@ pun=6 gets sda and a harddisk at pun=0 gets sdb. If you like to have the same SCSI-device order, as in DOS, OS-9 or OS/2, just use this parameter. + fast SCSI-I/O in synchronous mode is done at 5 MHz for IBM- + SCSI-devices. SCSI-2 Fast/Wide Adapter/A external bus + should then run at 10 MHz if Fast-SCSI is enabled, + and at 5 MHz if Fast-SCSI is disabled on the external + bus. This is the default setting when nothing is + specified here. + medium Synchronous rate is at 50% approximately, which means + 2.5 MHz for IBM SCSI-adapters and 5.0 MHz for F/W ext. + SCSI-bus (when Fast-SCSI speed enabled on external bus). + slow The slowest possible synchronous transfer rate is set. + This means 1.82 MHz for IBM SCSI-adapters and 2.0 MHz + for F/W external bus at Fast-SCSI speed on the external + bus. A further option is that you can force the SCSI-driver to accept a SCSI- subsystem at a certain I/O-address with a predefined adapter PUN. This @@ -805,7 +1004,7 @@ ibmmcascsi=adisplay,bypass This will use the advanced display mode for the model 95 LED display and - every SCSI-command passed to a attached device will get bypassed in order + every SCSI-command passed to an attached device will get bypassed in order not to use any of the subsystem built-in commands. ibmmcascsi=display,0x3558,7 @@ -837,9 +1036,9 @@ with OS/2 and DOS, you have to activate this flag in the kernel configuration or you should set 'ansi' as parameter for the kernel. The parameter 'normal' sets the new industry standard, starting - from pun 0, scaning up to pun 6. This allows you to change your + from pun 0, scanning up to pun 6. This allows you to change your opinion still after having already compiled the kernel. - Q: Why can I not find the IBM MCA SCSI support in the config menue? + Q: Why I cannot find the IBM MCA SCSI support in the config menue? A: You have to activate MCA bus support, first. Q: Where can I find the latest info about this driver? A: See the file MAINTAINERS for the current WWW-address, which offers @@ -849,13 +1048,9 @@ A: Just force it to be recognized by kernel parameters. See section 5.1. Q: The driver screws up, if it starts to probe SCSI-devices, is there some way out of it? - A: This is based on some problems with the driver. In such cases, send - e-mail to the maintainer. If you are owner of a model with the serial - number 95XX, just send as subject NOTIFY 95XX PROBLEM and the - maintainer immediately knows about your problem. But please: - Check your hardware and only if it works fine with other operating - systems, send E-Mail to me to notify the troubles. See the homepage - for how to send bug-reports or please read the next Q/A, here: + A: Yes, that was some recognition problem of the correct SCSI-adapter + and its I/O base addresses. Upgrade your driver to the latest release + and it should be fine again. Q: I get a message: panic IBM MCA SCSI: command error .... , what can I do against this? A: Previously, I followed the way by ignoring command errors by using @@ -867,8 +1062,8 @@ ibmmcascsi=forgiveall. Are there other possibilities to prevent such panics? A: No, get just the latest release of the driver and it should work - better and better with increasing version number. Forget this - ibmmcascsi=forgiveall, as also ignorecmd are obsolete. + better and better with increasing version number. Forget about this + ibmmcascsi=forgiveall, as also ignorecmd are obsolete.! Q: Linux panics or stops without any comment, but it is probable, that my harddisk(s) have bad blocks. A: Sorry, the bad-block handling is still a feeble point of this driver, @@ -893,10 +1088,45 @@ Astonishingly, reset works in most cases quite ok, but the harddisks won't run in synchonous mode anymore after a reset, until you reboot. Q: Why does my XXX w/Cache adapter not use read-prefetch? - A: w/Cache technical manuals are incoming here, so if I understood the - command of read-prefetch, it should be an easy thing to get harddisks - read in read-prefetch with w/Cache controllers. Some weeks or months, - still ahead and a lot of work still to do, sigh ... + A: Ok, that is not completely possible. If a cache is present, the + adapter tries to use it internally. Explicitly, one can use the cache + with a read prefetch command, maybe in future, but this requires + some major overhead of SCSI-commands that risks the performance to + go down more than it gets improved. Tests with that are running. + Q: I have a IBM SCSI-2 Fast/Wide adapter, it boots in some way and hangs. + A: Yes, that is understood, as for sure, your SCSI-2 Fast/Wide adapter + was in such a case recognized as integrated SCSI-adapter or something + else, but not as the correct adapter. As the I/O-ports get assigned + wrongly by that reason, the system should crash in most cases. You + should upgrade to the latest release of the SCSI-driver. The + recommended version is 3.2 or later. Here, the F/W support is in + a stable and reliable condition. Wide-addressing is in addition + supported. + Q: I get a Ooops message and something like "killing interrupt". + A: The reason for this is that the IBM SCSI-subsystem only sends a + termination status back, if some error appeared. In former releases + of the driver, it was not checked, if the termination status block + is NULL. From version 3.2, it is taken care of this. + Q: I have a F/W adapter and the driver sees my internal SCSI-devices, + but ignores the external ones. + A: Select combined busmode in the config-program and check for that + no SCSI-id on the external devices appears on internal devices. + Reboot afterwards. Dual busmode is supported, but works only for the + internal bus, yet. External bus is still ignored. Take care for your + SCSI-ids. If combined bus-mode is activated, on some adapters, + the wide-addressing is not possible, so devices with ids between 8 + and 15 get ignored by the driver & adapter! + Q: I have a 9595 and I get a NMI during heavy SCSI I/O e.g. during fsck. + A COMMAND ERROR is reported and characters on the screen are missing. + Warm reboot is not possible. Things look like quite weired. + A: Check the processor type of your 9595. If you have an 80486 or 486DX-2 + processor complex on your mainboard and you compiled a kernel that + supports 80386 processors, it is possible, that the kernel cannot + keep track of the PS/2 interrupt handling and stops on an NMI. Just + compile a kernel for the correct processor type of your PS/2 and + everything should be fine. This is necessary even if one assumes, + that some 80486 system should be downward compatible to 80386 + software. 5.3 Bugreports -------------- @@ -909,7 +1139,9 @@ Zubkoff, as Linus is burried in E-Mail and Leonard is supervising all SCSI-drivers and won't have the time left to look inside every single driver to fix a bug and especially DO NOT send modified code to Linus - Torvalds, which has not been checked here!!! Recently, I got a lot of + Torvalds or Alan J. Cox which has not been checked here!!! They are both + quite burried in E-mail (as me, sometimes, too) and one should first check + for problems on my local teststand. Recently, I got a lot of bugreports for errors in the ibmmca.c code, which I could not imagine, but a look inside some Linux-distribution showed me quite often some modified code, which did no longer work on most other machines than the one of the @@ -934,23 +1166,36 @@ http://www.uni-mainz.de/~langm000/linux.html Here you can find info about the background of this driver, patches, - news and a bugreport form. + troubleshooting support, news and a bugreport form. Please check that + WWW-page regularly for latest hints. + + For the bugreport, please fill out the formular on the corresponding + WWW-page. Read the dedicated instructions and write as much as you + know about your problem. If you do not like such formulars, please send + some e-mail directly, but at least with the same information as required by + the formular. + + If you have extensive bugreports, including Ooops messages and + screen-shots, please feel free to send it directly to the address + of the maintainer, too. The current address of the maintainer is: + + Michael Lang 6 References ------------ - The source of information is "Update for the PS/2 Hardware - Interface Technical Reference, Common Interfaces", September 1991, - part number 04G3281, available in the U.S. for $21.75 at - 1-800-IBM-PCTB, elsewhere call your local friendly IBM - representative. E.g. in Germany, "Hallo IBM" works really great. - In addition to SCSI subsystem, this update contains fairly detailed - (at hardware register level) sections on diskette controller, - keyboard controller, serial port controller, VGA, and XGA. + IBM Corp., "Update for the PS/2 Hardware Interface Technical Reference, + Common Interfaces", Armonk, September 1991, PN 04G3281, + (available in the U.S. for $21.75 at 1-800-IBM-PCTB or in Germany for + around 40,-DM at "Hallo IBM"). - Additional information from "Personal System/2 Micro Channel SCSI - Adapter with Cache Technical Reference", March 1990, PN 68X2365, - probably available from the same source (or possibly found buried - in officemates desk). + IBM Corp., "Personal System/2 Micro Channel SCSI + Adapter with Cache Technical Reference", Armonk, March 1990, PN 68X2365. + + IBM Corp., "Personal System/2 Micro Channel SCSI + Adapter Technical Reference", Armonk, March 1990, PN 68X2397. + + IBM Corp., "SCSI-2 Fast/Wide Adapter/A Technical Reference - Dual Bus", + Armonk, March 1994, PN 83G7545. Friedhelm Schmidt, "SCSI-Bus und IDE-Schnittstelle - Moderne Peripherie- Schnittstellen: Hardware, Protokollbeschreibung und Anwendung", 2. Aufl. @@ -965,14 +1210,101 @@ Helmut Rompel, "IBM Computerwelt GUIDE", What is what bei IBM., Systeme * Programme * Begriffe, IWT-Verlag GmbH - Muenchen, 1988 - 7 Trademarks + 7 Credits to + ------------ + 7.1 People + ---------- + Klaus Grimm + who already a long time ago gave me the old code from the + SCSI-driver in order to get it running for some old machine + in our institute. + Martin Kolinek + who wrote the first release of the IBM SCSI-subsystem driver. + Chris Beauregard + who for a long time maintained MCA-Linux and the SCSI-driver + in the beginning. Chris, wherever you are: Cheers to you! + Klaus Kudielka + with whom in the 2.1.x times, I had a quite fruitful + cooperation to get the driver running as a module and to get + it running with multiple SCSI-adapters. + David Weinehall + for his excellent maintenance of the MCA-stuff and the quite + detailed bug reports and ideas for this driver (and his + patience ;-)). + Alan J. Cox + for his bugreports and his bold activities in cross-checking + the driver-code with his teststand. + + 7.2 Sponsors & Supporters + ------------------------- + "Hallo IBM", + IBM-Deutschland GmbH + the service of IBM-Deutschland for customers. Their E-Mail + service is unbeatable. Whatever old stuff I asked for, I + always got some helpful answers. + Karl-Otto Reimers, + IBM Klub - Sparte IBM Geschichte, Sindelfingen + for sending me a copy of the w/Cache manual from the + IBM-Deutschland archives. + Harald Staiger + for his extensive hardware donations which allows me today + still to test the driver in various constellations. + Erich Fritscher + for his very kind sponsoring. + Louis Ohland, + Charles Lasitter + for support by shipping me an IBM SCSI-2 Fast/Wide manual. + In addition, the contribution of various hardware is quite + decessive and will make it possible to add FWSR (RAID) + adapter support to the driver in the near future! So, + complaints about no RAID support won't remain forever. + Yes, folks, that is no joke, RAID support is going to rise! + Erik Weber + for the great deal we made about a model 9595 and the nice + surrounding equipment and the cool trip to Mannheim + second-hand computer market. + Anthony Hogbin + for his direct shipment of a SCSI F/W adapter, which allowed + me immediately on the first stage to try it on model 8557 + together with onboard SCSI adapter and some SCSI w/Cache. + Andreas Hotz + for his support by memory and an IBM SCSI-adapter. Collecting + all this together now allows me to try really things with + the driver at maximum load and variety on various models in + a very quick and efficient way. + Peter Jennewein + for his model 30, which serves me as part of my teststand + and his cool remark about how you make an ordinary diskette + drive working and how to connect it to an IBM-diskette port. + Johannes Gutenberg-University, Mainz & + Institut fuer Kernphysik, MAMI + for the offered space, the link, placed on the central + homepage and the space to store and offer the driver and + related material and the free working times, which allow + me to answer all your e-mail. + + 8 Trademarks ------------ IBM, PS/2, OS/2, Microchannel are registered trademarks of International - Business Machines Corp. + Business Machines Corporation MS-DOS is a registered trademark of Microsoft Corporation - OS-9 is a registered trademark of Microware Systems + Microware, OS-9 are registered trademarks of Microware Systems + + 9 Disclaimer + ------------ + Beside the GNU public license and the dependant disclaimers and disclaimers + concerning the Linux-kernel in special, this SCSI-driver comes without any + warranty. Its functionality is tested as good as possible on certain + machines and combinations of computer hardware, which does not exclude, + that dataloss or severe damage of hardware is possible while using this + part of software on some arbitrary computer hardware or in combination + with other software packages. It is highly recommended to make backup + copies of your data before using this software. + + This driver supports hardware, produced by International Business Machines + Corporation (IBM). ------ Michael Lang diff -u --recursive --new-file v2.4.0-test5/linux/drivers/scsi/README.st linux/drivers/scsi/README.st --- v2.4.0-test5/linux/drivers/scsi/README.st Wed Apr 26 16:34:08 2000 +++ linux/drivers/scsi/README.st Mon Aug 7 22:52:10 2000 @@ -2,7 +2,7 @@ The driver is currently maintained by Kai M{kisara (email Kai.Makisara@metla.fi) -Last modified: Sat Apr 22 14:50:25 2000 by makisara@kai.makisara.local +Last modified: Sat Aug 5 10:29:07 2000 by makisara@kai.makisara.local BASICS @@ -67,7 +67,7 @@ In variable block mode, the byte count in write() determines the size of the physical block on tape. When reading, the drive reads the next tape block and returns to the user the data if the read() byte count -is at least the block size. Otherwise the data is truncated. +is at least the block size. Otherwise, error ENOMEM is returned. In fixed block mode, the data transfer between the drive and the driver is in multiples of the block size. The write() byte count must diff -u --recursive --new-file v2.4.0-test5/linux/drivers/scsi/ibmmca.c linux/drivers/scsi/ibmmca.c --- v2.4.0-test5/linux/drivers/scsi/ibmmca.c Tue Dec 14 01:27:24 1999 +++ linux/drivers/scsi/ibmmca.c Mon Jul 31 11:35:12 2000 @@ -7,7 +7,7 @@ * See the file README.ibmmca for a detailed description of this driver, * the commandline arguments and the history of its development. * See the WWW-page: http://www.uni-mainz.de/~langm000/linux.html for latest - * updates and info. + * updates, info and ADF-files for adapters supported by this driver. */ /******************* HEADER FILE INCLUDES ************************************/ @@ -16,9 +16,12 @@ #endif /* choose adaption for Kernellevel */ -#define local_LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,65) +#define OLDKERN +#else +#undef OLDKERN +#endif -#include #include #include #include @@ -31,8 +34,13 @@ #include #include #include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,17) #include +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) +#include +#endif #include +#include #include "sd.h" #include "scsi.h" #include "hosts.h" @@ -42,6 +50,7 @@ /******************* LOCAL DEFINES *******************************************/ +/* milliseconds of delay for timing out reset. */ #ifndef mdelay #define mdelay(a) udelay((a) * 1000) #endif @@ -49,7 +58,7 @@ /*--------------------------------------------------------------------*/ /* current version of this driver-source: */ -#define IBMMCA_SCSI_DRIVER_VERSION "3.1e" +#define IBMMCA_SCSI_DRIVER_VERSION "3.2" /*--------------------------------------------------------------------*/ @@ -60,17 +69,17 @@ /* driver debugging - #undef all for normal operation */ /* if defined: count interrupts and ignore this special one: */ -#undef IM_DEBUG_TIMEOUT 50 +#undef IM_DEBUG_TIMEOUT 50 #define TIMEOUT_PUN 0 #define TIMEOUT_LUN 0 /* verbose interrupt: */ -#undef IM_DEBUG_INT +#undef IM_DEBUG_INT /* verbose queuecommand: */ -#undef IM_DEBUG_CMD +#undef IM_DEBUG_CMD /* verbose queucommand for specific SCSI-device type: */ -#undef IM_DEBUG_CMD_SPEC_DEV +#undef IM_DEBUG_CMD_SPEC_DEV /* verbose device probing */ -#undef IM_DEBUG_PROBE +#define IM_DEBUG_PROBE /* device type that shall be displayed on syslog (only during debugging): */ #define IM_DEBUG_CMD_DEVICE TYPE_TAPE @@ -103,6 +112,7 @@ /*note: the lower nibble specifies the device(0-14), or subsystem(15) */ #define IM_SCB_CMD_COMPLETED 0x10 #define IM_SCB_CMD_COMPLETED_WITH_RETRIES 0x50 +#define IM_LOOP_SCATTER_BUFFER_FULL 0x60 #define IM_ADAPTER_HW_FAILURE 0x70 #define IM_IMMEDIATE_CMD_COMPLETED 0xa0 #define IM_CMD_COMPLETED_WITH_FAILURE 0xc0 @@ -146,7 +156,7 @@ unsigned short length; /*block length, on SCSI device */ } blk; - unsigned char scsi_command[12]; /*other scsi command */ + unsigned char scsi_command[12]; /*other scsi command */ } u2; }; @@ -158,6 +168,31 @@ unsigned long byte_length; }; +/*structure returned by a get_pos_info command: */ +struct im_pos_info + { + unsigned short pos_id; /* adapter id */ + unsigned char pos_3a; /* pos 3 (if pos 6 = 0) */ + unsigned char pos_2; /* pos 2 */ + unsigned char int_level; /* interrupt level IRQ 11 or 14 */ + unsigned char pos_4a; /* pos 4 (if pos 6 = 0) */ + unsigned short connector_size; /* MCA connector size: 16 or 32 Bit */ + unsigned char num_luns; /* number of supported luns per device */ + unsigned char num_puns; /* number of supported puns */ + unsigned char pacing_factor; /* pacing factor */ + unsigned char num_ldns; /* number of ldns available */ + unsigned char eoi_off; /* time EOI and interrupt inactive */ + unsigned char max_busy; /* time between reset and busy on */ + unsigned short cache_stat; /* ldn cachestat. Bit=1 = not cached */ + unsigned short retry_stat; /* retry status of ldns. Bit=1=disabled */ + unsigned char pos_4b; /* pos 4 (if pos 6 = 1) */ + unsigned char pos_3b; /* pos 3 (if pos 6 = 1) */ + unsigned char pos_6; /* pos 6 */ + unsigned char pos_5; /* pos 5 */ + unsigned short max_overlap; /* maximum overlapping requests */ + unsigned short num_bus; /* number of SCSI-busses */ + }; + /*values for SCB command word */ #define IM_NO_SYNCHRONOUS 0x0040 /*flag for any command */ #define IM_NO_DISCONNECT 0x0080 /*flag for any command */ @@ -168,6 +203,7 @@ #define IM_REQUEST_SENSE_CMD 0x1c08 #define IM_READ_CAPACITY_CMD 0x1c09 #define IM_DEVICE_INQUIRY_CMD 0x1c0b +#define IM_READ_LOGICAL_CMD 0x1c2a #define IM_OTHER_SCSI_CMD_CMD 0x241f /* unused, but supported, SCB commands */ @@ -183,6 +219,7 @@ #define IM_RETRY_ENABLE 0x2000 #define IM_POINTER_TO_LIST 0x1000 #define IM_SUPRESS_EXCEPTION_SHORT 0x0400 +#define IM_BYPASS_BUFFER 0x0200 #define IM_CHAIN_ON_NO_ERROR 0x0001 /*TSB (Termination Status Block) structure */ @@ -204,15 +241,17 @@ }; /*subsystem uses interrupt request level 14 */ -#define IM_IRQ 14 +#define IM_IRQ 14 +/*SCSI-2 F/W may evade to interrupt 11 */ +#define IM_IRQ_FW 11 /*--------------------------------------------------------------------*/ /* The model 95 doesn't have a standard activity light. Instead it - has a row of LEDs on the front. We use the last one as the activity - indicator if we think we're on a model 95. I suspect the model id - check will be either too narrow or too general, and some machines - won't have an activity indicator. Oh well... + has a row of alphanumerial LEDs on the front. We use the last one + as the activity indicator if we think we're on a model 95. I suspect + the model id check will be either too narrow or too general, and some + machines won't have an activity indicator. Oh well... The regular PS/2 disk led is turned on/off by bits 6,7 of system control port. @@ -222,6 +261,12 @@ #define MOD95_LED_PORT 0x108 /* system-control-register of PS/2s with diskindicator */ #define PS2_SYS_CTR 0x92 +/* activity displaying methods */ +#define LED_DISP 1 +#define LED_ADISP 2 +#define LED_ACTIVITY 4 + +#define CMD_FAIL 255 /* The SCSI-ID(!) of the accessed SCSI-device is shown on PS/2-95 machines' LED displays. ldn is no longer displayed here, because the ldn mapping is now @@ -230,30 +275,39 @@ interest, debugging or just for having fun. The left number gives the host-adapter number and the right shows the accessed SCSI-ID. */ -/* use_display is set by the ibmmcascsi=display command line arg */ -static int use_display = 0; -/* use_adisplay is set by ibmmcascsi=adisplay, which offers a higher - * level of displayed luxus on PS/2 95 (really fancy! :-))) */ -static int use_adisplay = 0; +/* display_mode is set by the ibmmcascsi= command line arg */ +static int display_mode = 0; +/* set default adapter timeout */ +static unsigned int adapter_timeout = 45; +/* for probing on feature-command: */ +static unsigned int global_command_error_excuse = 0; +/* global setting by command line for adapter_speed */ +static int global_adapter_speed = 0; /* full speed by default */ +/* Panel / LED on, do it right for F/W addressin, too. adisplay will + * just ignore ids>7, as the panel has only 7 digits available */ #define PS2_DISK_LED_ON(ad,id) {\ - if( use_display ) { outb((char)(id+48), MOD95_LED_PORT ); \ - outb((char)(ad+48), MOD95_LED_PORT+1); } \ - else if( use_adisplay ) { if (id<7) outb((char)(id+48), \ - MOD95_LED_PORT+1+id); outb((char)(ad+48), MOD95_LED_PORT); } \ - else outb(inb(PS2_SYS_CTR) | 0xc0, PS2_SYS_CTR); \ + if (display_mode & LED_DISP) { \ + if (id>9) \ + outw((ad+48)|((id+55)<<8), MOD95_LED_PORT ); \ + else \ + outw((ad+48)|((id+48)<<8), MOD95_LED_PORT ); } \ + else if (display_mode & LED_ADISP) { \ + if (id<7) outb((char)(id+48),MOD95_LED_PORT+1+id); \ + outb((char)(ad+48), MOD95_LED_PORT); } \ + if ((display_mode & LED_ACTIVITY)||(!display_mode)) \ + outb(inb(PS2_SYS_CTR) | 0xc0, PS2_SYS_CTR); \ } - +/* Panel / LED off */ /* bug fixed, Dec 15, 1997, where | was replaced by & here */ #define PS2_DISK_LED_OFF() {\ - if( use_display ) { outb( ' ', MOD95_LED_PORT ); \ - outb(' ', MOD95_LED_PORT+1); } \ - if ( use_adisplay ) { outb(' ',MOD95_LED_PORT ); \ - outb(' ',MOD95_LED_PORT+1); outb(' ',MOD95_LED_PORT+2); \ - outb(' ',MOD95_LED_PORT+3); outb(' ',MOD95_LED_PORT+4); \ - outb(' ',MOD95_LED_PORT+5); outb(' ',MOD95_LED_PORT+6); \ - outb(' ',MOD95_LED_PORT+7); } \ - else outb(inb(PS2_SYS_CTR) & 0x3f, PS2_SYS_CTR); \ + if (display_mode & LED_DISP) \ + outw(0x2020, MOD95_LED_PORT ); \ + else if (display_mode & LED_ADISP) { \ + outl(0x20202020,MOD95_LED_PORT); \ + outl(0x20202020,MOD95_LED_PORT+4); } \ + if ((display_mode & LED_ACTIVITY)||(!display_mode)) \ + outb(inb(PS2_SYS_CTR) & 0x3f, PS2_SYS_CTR); \ } /*--------------------------------------------------------------------*/ @@ -265,15 +319,37 @@ char *description; }; +/* types of different supported hardware that goes to hostdata special */ +#define IBM_SCSI2_FW 0 +#define IBM_7568_WCACHE 1 +#define IBM_EXP_UNIT 2 +#define IBM_SCSI_WCACHE 3 +#define IBM_SCSI 4 + +/* other special flags for hostdata structure */ +#define FORCED_DETECTION 100 +#define INTEGRATED_SCSI 101 + /* List of possible IBM-SCSI-adapters */ struct subsys_list_struct subsys_list[] = { - {0x8efc, "IBM Fast SCSI-2 Adapter"}, /* special = 0 */ - {0x8efd, "IBM 7568 Industrial Computer SCSI Adapter w/cache"}, /* special = 1 */ + {0x8efc, "IBM SCSI-2 F/W Adapter"}, /* special = 0 */ + {0x8efd, "IBM 7568 Industrial Computer SCSI Adapter w/Cache"}, /* special = 1 */ {0x8ef8, "IBM Expansion Unit SCSI Controller"},/* special = 2 */ {0x8eff, "IBM SCSI Adapter w/Cache"}, /* special = 3 */ {0x8efe, "IBM SCSI Adapter"}, /* special = 4 */ +}; + +/*for /proc filesystem, only valid in older kernel releases */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,27) +struct proc_dir_entry proc_scsi_ibmmca = +{ + PROC_SCSI_IBMMCA, 6, "ibmmca", + S_IFDIR | S_IRUGO | S_IXUGO, 2, + 0, 0, 0, NULL, NULL, NULL, NULL, + NULL, NULL, NULL }; +#endif /* Max number of logical devices (can be up from 0 to 14). 15 is the address of the adapter itself. */ @@ -286,11 +362,12 @@ struct im_tsb tsb; /* SCSI command complete status block structure */ struct im_sge sge[16]; /* scatter gather list structure */ unsigned char buf[256]; /* SCSI command return data buffer */ - Scsi_Cmnd *cmd; /* SCSI-command that is currently in progress */ - + Scsi_Cmnd *cmd; /* SCSI-command that is currently in progress */ int device_type; /* type of the SCSI-device. See include/scsi/scsi.h for interpretation of the possible values */ int block_length;/* blocksize of a particular logical SCSI-device */ + int cache_flag; /* 1 if this is uncached, 0 if cache is present for ldn */ + int retry_flag; /* 1 if adapter retry is disabled, 0 if enabled */ }; /* statistics of the driver during operations (for proc_info) */ @@ -302,6 +379,8 @@ int ldn_write_access[MAX_LOG_DEV+1]; /* total write-access on a ldn */ int ldn_inquiry_access[MAX_LOG_DEV+1]; /* total inquiries on a ldn */ int ldn_modeselect_access[MAX_LOG_DEV+1]; /* total mode selects on ldn */ + int scbs; /* short SCBs queued */ + int long_scbs; /* long SCBs queued */ int total_accesses; /* total accesses on all ldns */ int total_interrupts; /* total interrupts (should be same as total_accesses) */ @@ -318,12 +397,12 @@ struct ibmmca_hostdata { /* array of logical devices: */ - struct logical_device _ld[MAX_LOG_DEV+1]; + struct logical_device _ld[MAX_LOG_DEV+1]; /* array to convert (pun, lun) into logical device number: */ - unsigned char _get_ldn[8][8]; + unsigned char _get_ldn[16][8]; /*array that contains the information about the physical SCSI-devices attached to this host adapter: */ - unsigned char _get_scsi[8][8]; + unsigned char _get_scsi[16][8]; /* used only when checking logical devices: */ int _local_checking_phase_flag; /* report received interrupt: */ @@ -336,21 +415,30 @@ int _last_scsi_command[MAX_LOG_DEV+1]; /* identifier of the last SCSI-command type */ int _last_scsi_type[MAX_LOG_DEV+1]; - /* Counter that points on the next reassignable ldn for dynamical - remapping. The default value is 7, that is the first reassignable + /* last blockcount */ + int _last_scsi_blockcount[MAX_LOG_DEV+1]; + /* last locgical block address */ + unsigned long _last_scsi_logical_block[MAX_LOG_DEV+1]; + /* Counter that points on the next reassignable ldn for dynamical + remapping. The default value is 7, that is the first reassignable number in the list at boottime: */ int _next_ldn; /* Statistics-structure for this IBM-SCSI-host: */ struct Driver_Statistics _IBM_DS; - /* This hostadapters pos-registers pos2 and pos3 */ - unsigned _pos2, _pos3; + /* This hostadapters pos-registers pos2 until pos6 */ + unsigned _pos2, _pos3, _pos4, _pos5, _pos6; /* assign a special variable, that contains dedicated info about the adaptertype */ int _special; + /* connector size on the MCA bus */ + int _connector_size; + /* synchronous SCSI transfer rate bitpattern */ + int _adapter_speed; }; /* macros to access host data structure */ #define subsystem_pun(hi) (hosts[(hi)]->this_id) +#define subsystem_maxid(hi) (hosts[(hi)]->max_id) #define ld(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_ld) #define get_ldn(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_get_ldn) #define get_scsi(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_get_scsi) @@ -360,13 +448,21 @@ #define reset_status(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_reset_status) #define last_scsi_command(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_command) #define last_scsi_type(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_type) +#define last_scsi_blockcount(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_blockcount) +#define last_scsi_logical_block(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_logical_block) +#define last_scsi_type(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_type) #define next_ldn(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_next_ldn) #define IBM_DS(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_IBM_DS) #define special(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_special) +#define subsystem_connector_size(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_connector_size) +#define adapter_speed(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_adapter_speed) #define pos2(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos2) #define pos3(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos3) +#define pos4(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos4) +#define pos5(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos5) +#define pos6(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos6) -/* Define a arbitrary number as subsystem-marker-type. This number is, as +/* Define a arbitrary number as subsystem-marker-type. This number is, as described in the ANSI-SCSI-standard, not occupied by other device-types. */ #define TYPE_IBM_SCSI_ADAPTER 0x2F @@ -396,10 +492,6 @@ #define IM_RESET_NOT_IN_PROGRESS_NO_INT 4 #define IM_RESET_FINISHED_OK_NO_INT 5 -/* special flags for hostdata structure */ -#define FORCED_DETECTION 100 -#define INTEGRATED_SCSI 101 - /* define undefined SCSI-command */ #define NO_SCSI 0xffff @@ -409,22 +501,40 @@ static int io_port[IM_MAX_HOSTS] = { 0, 0, 0, 0, 0, 0, 0, 0 }; static int scsi_id[IM_MAX_HOSTS] = { 7, 7, 7, 7, 7, 7, 7, 7 }; +/* fill module-parameters only, when this define is present. + (that is kernel version 2.1.x) */ +#if defined(MODULE) +static char *boot_options = NULL; +#include +MODULE_PARM(boot_options, "s"); +MODULE_PARM(io_port, "1-" __MODULE_STRING(IM_MAX_HOSTS) "i"); +MODULE_PARM(scsi_id, "1-" __MODULE_STRING(IM_MAX_HOSTS) "i"); +MODULE_PARM(display, "1i"); +MODULE_PARM(adisplay, "1i"); +MODULE_PARM(bypass, "1i"); +MODULE_PARM(normal, "1i"); +MODULE_PARM(ansi, "1i"); +#endif /*counter of concurrent disk read/writes, to turn on/off disk led */ static int disk_rw_in_progress = 0; /* spinlock handling to avoid command clash while in operation */ +#ifndef OLDKERN spinlock_t info_lock = SPIN_LOCK_UNLOCKED; spinlock_t proc_lock = SPIN_LOCK_UNLOCKED; spinlock_t abort_lock = SPIN_LOCK_UNLOCKED; spinlock_t reset_lock = SPIN_LOCK_UNLOCKED; spinlock_t issue_lock = SPIN_LOCK_UNLOCKED; spinlock_t intr_lock = SPIN_LOCK_UNLOCKED; +#endif /* host information */ static int found = 0; -static struct Scsi_Host *hosts[IM_MAX_HOSTS+1] = { NULL }; -static unsigned int pos[8]; /* whole pos register-line */ +static struct Scsi_Host *hosts[IM_MAX_HOSTS+1] = { NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL }; +static unsigned int pos[8]; /* whole pos register-line for diagnosis */ /* Taking into account the additions, made by ZP Gu. * This selects now the preset value from the configfile and * offers the 'normal' commandline option to be accepted */ @@ -439,32 +549,40 @@ /******************* FUNCTIONS IN FORWARD DECLARATION ************************/ static void interrupt_handler (int, void *, struct pt_regs *); +#ifndef OLDKERN static void do_interrupt_handler (int, void *, struct pt_regs *); +#endif static void issue_cmd (int, unsigned long, unsigned char); static void internal_done (Scsi_Cmnd * cmd); -static void check_devices (int); -static int immediate_assign(int, unsigned int, unsigned int, unsigned int, +static void check_devices (int, int); +static int immediate_assign(int, unsigned int, unsigned int, unsigned int, unsigned int); +static int immediate_feature(int, unsigned int, unsigned int); #ifdef CONFIG_IBMMCA_SCSI_DEV_RESET static int immediate_reset(int, unsigned int); #endif static int device_inquiry(int, int); static int read_capacity(int, int); +static int get_pos_info(int); static char *ti_p(int); static char *ti_l(int); +static char *ibmrate(unsigned int, int); +static int probe_display(int); +static int probe_bus_mode(int); static int device_exists (int, int, int *, int *); static struct Scsi_Host *ibmmca_register(Scsi_Host_Template *, - int, int, char *); - + int, int, int, char *); /* local functions needed for proc_info */ static int ldn_access_load(int, int); static int ldn_access_total_read_write(int); static int bypass_controller = 0; /* bypass integrated SCSI-cmd set flag */ + /*--------------------------------------------------------------------*/ /******************* LOCAL FUNCTIONS IMPLEMENTATION *************************/ +#ifndef OLDKERN /* newer Kernels need the spinlock interrupt handler */ static void do_interrupt_handler (int irq, void *dev_id, struct pt_regs *regs) { @@ -473,8 +591,9 @@ spin_lock_irqsave(&io_request_lock, flags); interrupt_handler(irq, dev_id, regs); spin_unlock_irqrestore(&io_request_lock, flags); - return; + return; } +#endif static void interrupt_handler (int irq, void *dev_id, struct pt_regs *regs) { @@ -482,20 +601,17 @@ unsigned int intr_reg; unsigned int cmd_result; unsigned int ldn; - static unsigned long flags; + unsigned long flags; Scsi_Cmnd *cmd; - int errorflag; - int interror; - - host_index=0; /* make sure, host_index is 0, else this won't work and - never dare to ask, what happens, if an interrupt-handler - does not work :-((( .... */ + int lastSCSI; + + host_index = 0; /* make sure, host_index is 0 */ /* search for one adapter-response on shared interrupt */ while (hosts[host_index] && !(inb(IM_STAT_REG(host_index)) & IM_INTR_REQUEST)) host_index++; - + /* return if some other device on this IRQ caused the interrupt */ if (!hosts[host_index]) return; @@ -507,88 +623,126 @@ reset_status(host_index) = IM_RESET_NOT_IN_PROGRESS; return; } - - /*get command result and logical device */ - intr_reg = inb (IM_INTR_REG(host_index)); - cmd_result = intr_reg & 0xf0; - ldn = intr_reg & 0x0f; - + /*must wait for attention reg not busy, then send EOI to subsystem */ - while (1) + while (1) { +#ifdef OLDKERN + save_flags(flags); + cli(); +#else spin_lock_irqsave(&intr_lock, flags); - if (!(inb (IM_STAT_REG(host_index)) & IM_BUSY)) +#endif + /* if (!(inb (IM_STAT_REG(host_index)) & IM_BUSY)) */ + if ((inb(IM_STAT_REG(host_index)) & 0xf) == (IM_CMD_REG_EMPTY | IM_INTR_REQUEST)) break; +#ifdef OLDKERN + restore_flags(flags); +#else spin_unlock_irqrestore(&intr_lock, flags); +#endif } - outb (IM_EOI | ldn, IM_ATTN_REG(host_index)); + /*get command result and logical device */ + intr_reg = (unsigned char)(inb (IM_INTR_REG(host_index))); + cmd_result = intr_reg & 0xf0; + ldn = intr_reg & 0x0f; + /* get the last_scsi_command here */ - interror = last_scsi_command(host_index)[ldn]; - spin_unlock_irqrestore(&intr_lock, flags); - errorflag = 0; /* no errors by default */ + lastSCSI = last_scsi_command(host_index)[ldn]; + /*these should never happen (hw fails, or a local programming bug) */ - if (cmd_result == IM_ADAPTER_HW_FAILURE) - { - printk("\n"); - printk("IBM MCA SCSI: ERROR - subsystem hardware failure!\n"); - printk(" Last SCSI-command=0x%X, ldn=%d, host=%d.\n", - last_scsi_command(host_index)[ldn],ldn,host_index); - errorflag = 1; - } - if (cmd_result == IM_SOFTWARE_SEQUENCING_ERROR) - { - printk("\n"); - printk("IBM MCA SCSI: ERROR - software sequencing error!\n"); - printk(" Last SCSI-command=0x%X, ldn=%d, host=%d.\n", - last_scsi_command(host_index)[ldn],ldn,host_index); - errorflag = 1; + if (!global_command_error_excuse) + { + switch (cmd_result) + { /* Prevent from Ooopsing on error to show the real reason */ + case IM_ADAPTER_HW_FAILURE: + case IM_SOFTWARE_SEQUENCING_ERROR: + case IM_CMD_ERROR: + printk("\nIBM MCA SCSI: Fatal Subsystem ERROR!\n"); + printk(" Last cmd=0x%x, ena=%x, len=",lastSCSI, + ld(host_index)[ldn].scb.enable); + if (ld(host_index)[ldn].cmd) + printk("%ld/%ld",(long)(ld(host_index)[ldn].cmd->request_bufflen), + (long)(ld(host_index)[ldn].scb.sys_buf_length)); + else + printk("none"); + printk(", "); + if (ld(host_index)[ldn].cmd) + printk("Blocksize=%d",ld(host_index)[ldn].scb.u2.blk.length); + else + printk("Blocksize=none"); + printk(", host=0x%x, ldn=0x%x\n",host_index, ldn); + if (ld(host_index)[ldn].cmd) + { + printk("Blockcount=%d/%d\n",last_scsi_blockcount(host_index)[ldn], + ld(host_index)[ldn].scb.u2.blk.count); + printk("Logical block=%lx/%lx\n",last_scsi_logical_block(host_index)[ldn], + ld(host_index)[ldn].scb.u1.log_blk_adr); + } + printk("Reason given: %s\n", + (cmd_result==IM_ADAPTER_HW_FAILURE) ? "HARDWARE FAILURE" : + (cmd_result==IM_SOFTWARE_SEQUENCING_ERROR) ? "SOFTWARE SEQUENCING ERROR" : + (cmd_result==IM_CMD_ERROR) ? "COMMAND ERROR" : "UNKNOWN"); + /* if errors appear, enter this section to give detailed info */ + printk("IBM MCA SCSI: Subsystem Error-Status follows:\n"); + printk(" Command Type................: %x\n", + last_scsi_type(host_index)[ldn]); + printk(" Attention Register..........: %x\n", + inb (IM_ATTN_REG(host_index))); + printk(" Basic Control Register......: %x\n", + inb (IM_CTR_REG(host_index))); + printk(" Interrupt Status Register...: %x\n", + intr_reg); + printk(" Basic Status Register.......: %x\n", + inb (IM_STAT_REG(host_index))); + if ((last_scsi_type(host_index)[ldn]==IM_SCB)|| + (last_scsi_type(host_index)[ldn]==IM_LONG_SCB)) + { + printk(" SCB-Command.................: %x\n", + ld(host_index)[ldn].scb.command); + printk(" SCB-Enable..................: %x\n", + ld(host_index)[ldn].scb.enable); + printk(" SCB-logical block address...: %lx\n", + ld(host_index)[ldn].scb.u1.log_blk_adr); + printk(" SCB-system buffer address...: %lx\n", + ld(host_index)[ldn].scb.sys_buf_adr); + printk(" SCB-system buffer length....: %lx\n", + ld(host_index)[ldn].scb.sys_buf_length); + printk(" SCB-tsb address.............: %lx\n", + ld(host_index)[ldn].scb.tsb_adr); + printk(" SCB-Chain address...........: %lx\n", + ld(host_index)[ldn].scb.scb_chain_adr); + printk(" SCB-block count.............: %x\n", + ld(host_index)[ldn].scb.u2.blk.count); + printk(" SCB-block length............: %x\n", + ld(host_index)[ldn].scb.u2.blk.length); + } + printk(" Send this report to the maintainer.\n"); + panic("IBM MCA SCSI: Fatal errormessage from the subsystem (0x%X,0x%X)!\n", + lastSCSI,cmd_result); + break; + } } - if (cmd_result == IM_CMD_ERROR) - { - printk("\n"); - printk("IBM MCA SCSI: ERROR - command error!\n"); - printk(" Last SCSI-command=0x%X, ldn=%d, host=%d.\n", - last_scsi_command(host_index)[ldn],ldn,host_index); - errorflag = 1; - } - if (errorflag) - { /* if errors appear, enter this section to give detailed info */ - printk("IBM MCA SCSI: Subsystem Error-Status follows:\n"); - printk(" Command Type................: %x\n", - last_scsi_type(host_index)[ldn]); - printk(" Attention Register..........: %x\n", - inb (IM_ATTN_REG(host_index))); - printk(" Basic Control Register......: %x\n", - inb (IM_CTR_REG(host_index))); - printk(" Interrupt Status Register...: %x\n", - intr_reg); - printk(" Basic Status Register.......: %x\n", - inb (IM_STAT_REG(host_index))); - if ((last_scsi_type(host_index)[ldn]==IM_SCB)|| - (last_scsi_type(host_index)[ldn]==IM_LONG_SCB)) - { - printk(" SCB End Status Word.........: %x\n", - ld(host_index)[ldn].tsb.end_status); - printk(" Command Status..............: %x\n", - ld(host_index)[ldn].tsb.cmd_status); - printk(" Device Status...............: %x\n", - ld(host_index)[ldn].tsb.dev_status); - printk(" Command Error...............: %x\n", - ld(host_index)[ldn].tsb.cmd_error); - printk(" Device Error................: %x\n", - ld(host_index)[ldn].tsb.dev_error); - printk(" Last SCB Address (LSW)......: %x\n", - ld(host_index)[ldn].tsb.low_of_last_scb_adr); - printk(" Last SCB Address (MSW)......: %x\n", - ld(host_index)[ldn].tsb.high_of_last_scb_adr); + else + { /* The command error handling is made silent, but we tell the + * calling function, that there is a reported error from the + * adapter. */ + switch (cmd_result) + { + case IM_ADAPTER_HW_FAILURE: + case IM_SOFTWARE_SEQUENCING_ERROR: + case IM_CMD_ERROR: + global_command_error_excuse = CMD_FAIL; + break; + default: + global_command_error_excuse = 0; + break; } - printk(" Send report to the maintainer.\n"); - panic("IBM MCA SCSI: Fatal errormessage from the subsystem!\n"); - } - + } + /* if no panic appeared, increase the interrupt-counter */ IBM_DS(host_index).total_interrupts++; - + /*only for local checking phase */ if (local_checking_phase_flag(host_index)) { @@ -596,8 +750,15 @@ got_interrupt(host_index) = 1; reset_status(host_index) = IM_RESET_FINISHED_OK; last_scsi_command(host_index)[ldn] = NO_SCSI; + + outb (IM_EOI | ldn, IM_ATTN_REG(host_index)); +#ifdef OLDKERN + restore_flags(flags); +#else + spin_unlock_irqrestore(&intr_lock, flags); +#endif return; - } + } /*handling of commands coming from upper level of scsi driver */ else { @@ -622,24 +783,39 @@ } stat_result(host_index) = cmd_result; last_scsi_command(host_index)[ldn] = NO_SCSI; + last_scsi_type(host_index)[ldn] = 0; + outb (IM_EOI | ldn, IM_ATTN_REG(host_index)); +#ifdef OLDKERN + restore_flags(flags); +#else + spin_unlock_irqrestore(&intr_lock, flags); +#endif return; } else if (last_scsi_command(host_index)[ldn] == IM_ABORT_IMM_CMD) { /* react on SCSI abort command */ #ifdef IM_DEBUG_PROBE printk("IBM MCA SCSI: Interrupt from SCSI-abort.\n"); -#endif +#endif disk_rw_in_progress = 0; PS2_DISK_LED_OFF(); cmd = ld(host_index)[ldn].cmd; + ld(host_index)[ldn].cmd = NULL; if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE) cmd->result = DID_NO_CONNECT << 16; else cmd->result = DID_ABORT << 16; stat_result(host_index) = cmd_result; last_scsi_command(host_index)[ldn] = NO_SCSI; + last_scsi_type(host_index)[ldn] = 0; + outb (IM_EOI | ldn, IM_ATTN_REG(host_index)); +#ifdef OLDKERN + restore_flags(flags); +#else + spin_unlock_irqrestore(&intr_lock, flags); +#endif if (cmd->scsi_done) - (cmd->scsi_done) (cmd); /* should be the internal_done */ + (cmd->scsi_done)(cmd); /* should be the internal_done */ return; } else @@ -649,36 +825,59 @@ reset_status(host_index) = IM_RESET_FINISHED_OK; stat_result(host_index) = cmd_result; last_scsi_command(host_index)[ldn] = NO_SCSI; + + outb (IM_EOI | ldn, IM_ATTN_REG(host_index)); +#ifdef OLDKERN + restore_flags(flags); +#else + spin_unlock_irqrestore(&intr_lock, flags); +#endif return; - } + } } last_scsi_command(host_index)[ldn] = NO_SCSI; + last_scsi_type(host_index)[ldn] = 0; cmd = ld(host_index)[ldn].cmd; + ld(host_index)[ldn].cmd = NULL; #ifdef IM_DEBUG_TIMEOUT if (cmd) { - if ((cmd->target == TIMEOUT_PUN)&&(cmd->lun == TIMEOUT_LUN)) + if ((cmd->target == TIMEOUT_PUN)&& + (cmd->lun == TIMEOUT_LUN)) { printk("IBM MCA SCSI: Ignoring interrupt from pun=%x, lun=%x.\n", cmd->target, cmd->lun); + outb (IM_EOI | ldn, IM_ATTN_REG(host_index)); +#ifdef OLDKERN + restore_flags(flags); +#else + spin_unlock_irqrestore(&intr_lock, flags); +#endif return; } } #endif /*if no command structure, just return, else clear cmd */ if (!cmd) - return; - ld(host_index)[ldn].cmd = NULL; - + { + outb (IM_EOI | ldn, IM_ATTN_REG(host_index)); +#ifdef OLDKERN + restore_flags(flags); +#else + spin_unlock_irqrestore(&intr_lock, flags); +#endif + return; + } + #ifdef IM_DEBUG_INT - printk("cmd=%02x ireg=%02x ds=%02x cs=%02x de=%02x ce=%02x\n", - cmd->cmnd[0], intr_reg, - ld(host_index)[ldn].tsb.dev_status, + printk("cmd=%02x ireg=%02x ds=%02x cs=%02x de=%02x ce=%02x\n", + cmd->cmnd[0], intr_reg, + ld(host_index)[ldn].tsb.dev_status, ld(host_index)[ldn].tsb.cmd_status, - ld(host_index)[ldn].tsb.dev_error, + ld(host_index)[ldn].tsb.dev_error, ld(host_index)[ldn].tsb.cmd_error); #endif - + /*if this is end of media read/write, may turn off PS/2 disk led */ if ((ld(host_index)[ldn].device_type!=TYPE_NO_LUN)&& (ld(host_index)[ldn].device_type!=TYPE_NO_DEVICE)) @@ -697,41 +896,73 @@ } /* IBM describes the status-mask to be 0x1e, but this is not conform - * with SCSI-defintion, I suppose, it is a printing error in the - * technical reference and assume as mask 0x3e. (ML) */ - cmd->result = (ld(host_index)[ldn].tsb.dev_status & 0x3e); - /* write device status into cmd->result, and call done function */ + * with SCSI-defintion, I suppose, the reason for it is that IBM + * adapters do not support CMD_TERMINATED, TASK_SET_FULL and + * ACA_ACTIVE as returning statusbyte information. (ML) */ if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE) - IBM_DS(host_index).total_errors++; - if (interror == NO_SCSI) /* unexpected interrupt :-( */ - cmd->result |= DID_BAD_INTR << 16; + { + cmd->result = (unsigned char)(ld(host_index)[ldn].tsb.dev_status & 0x1e); + IBM_DS(host_index).total_errors++; + } else + cmd->result = 0; + /* write device status into cmd->result, and call done function */ + if (lastSCSI == NO_SCSI) /* unexpected interrupt :-( */ + cmd->result |= DID_BAD_INTR << 16; + else /* things went right :-) */ cmd->result |= DID_OK << 16; - (cmd->scsi_done) (cmd); - } - if (interror == NO_SCSI) + outb (IM_EOI | ldn, IM_ATTN_REG(host_index)); +#ifdef OLDKERN + restore_flags(flags); +#else + spin_unlock_irqrestore(&intr_lock, flags); +#endif + /* This is for Kernel 2.2.x. Something weired happens here. + * Between the command got queued and the interrupt is released, + * the flags sometimes contain different values, which must + * be a strange thing. E.g. it appears when cold-booting with a + * tape drive at id0. */ + cmd->flags &= 0x3f; + if (cmd->scsi_done) + (cmd->scsi_done)(cmd); + } + if (lastSCSI == NO_SCSI) printk("IBM MCA SCSI: WARNING - Interrupt from non-pending SCSI-command!\n"); return; } /*--------------------------------------------------------------------*/ -static void issue_cmd (int host_index, unsigned long cmd_reg, +static void issue_cmd (int host_index, unsigned long cmd_reg, unsigned char attn_reg) { static unsigned long flags; - /* must wait for attention reg not busy */ + /* must wait for attention reg not busy */ while (1) { +#ifdef OLDKERN + save_flags(flags); + cli(); +#else spin_lock_irqsave(&issue_lock, flags); - if (!(inb (IM_STAT_REG(host_index)) & IM_BUSY)) +#endif + if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY)) break; +#ifdef OLDKERN + restore_flags(flags); +#else spin_unlock_irqrestore(&issue_lock, flags); +#endif } /*write registers and enable system interrupts */ outl (cmd_reg, IM_CMD_REG(host_index)); outb (attn_reg, IM_ATTN_REG(host_index)); +#ifdef OLDKERN + restore_flags(flags); +#else spin_unlock_irqrestore(&issue_lock, flags); +#endif + return; } /*--------------------------------------------------------------------*/ @@ -739,75 +970,70 @@ static void internal_done (Scsi_Cmnd * cmd) { cmd->SCp.Status++; + return; } /*--------------------------------------------------------------------*/ /* SCSI-SCB-command for device_inquiry */ static int device_inquiry(int host_index, int ldn) -{ +{ int retries; - Scsi_Cmnd *cmd; + Scsi_Cmnd cmd; struct im_scb *scb; struct im_tsb *tsb; unsigned char *buf; - + scb = &(ld(host_index)[ldn].scb); tsb = &(ld(host_index)[ldn].tsb); buf = (unsigned char *)(&(ld(host_index)[ldn].buf)); ld(host_index)[ldn].tsb.dev_status = 0; /* prepare stusblock */ - cmd = kmalloc(sizeof(*cmd), GFP_KERNEL|GFP_DMA); - if(cmd==NULL) - { - printk(KERN_ERR "ibmmca: out of memory for inquiry.\n"); - return 0; - } if (bypass_controller) { /* fill the commonly known field for device-inquiry SCSI cmnd */ - cmd->cmd_len = 6; - memset (&(cmd->cmnd), 0x0, sizeof(char) * cmd->cmd_len); - cmd->cmnd[0] = INQUIRY; /* device inquiry */ - cmd->cmnd[4] = 0xff; /* return buffer size = 255 */ - } + cmd.cmd_len = 6; + memset (&(cmd.cmnd), 0x0, sizeof(char) * cmd.cmd_len); + cmd.cmnd[0] = INQUIRY; /* device inquiry */ + cmd.cmnd[4] = 0xff; /* return buffer size = 255 */ + } for (retries = 0; retries < 3; retries++) { if (bypass_controller) { /* bypass the hardware integrated command set */ - scb->command = IM_OTHER_SCSI_CMD_CMD; - scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT; - scb->u1.scsi_cmd_length = cmd->cmd_len; - memcpy (scb->u2.scsi_command, &(cmd->cmnd), cmd->cmd_len); + scb->command = IM_OTHER_SCSI_CMD_CMD | IM_NO_DISCONNECT; + scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER; + scb->u1.scsi_cmd_length = cmd.cmd_len; + memcpy (scb->u2.scsi_command, &(cmd.cmnd), cmd.cmd_len); last_scsi_command(host_index)[ldn] = INQUIRY; - last_scsi_type(host_index)[ldn] = IM_SCB; + last_scsi_type(host_index)[ldn] = IM_LONG_SCB; } else { /*fill scb with inquiry command */ - scb->command = IM_DEVICE_INQUIRY_CMD; - scb->enable = IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT; + scb->command = IM_DEVICE_INQUIRY_CMD | IM_NO_DISCONNECT; + scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT; last_scsi_command(host_index)[ldn] = IM_DEVICE_INQUIRY_CMD; - last_scsi_type(host_index)[ldn] = IM_SCB; + last_scsi_type(host_index)[ldn] = IM_SCB; } scb->sys_buf_adr = virt_to_bus(buf); scb->sys_buf_length = 0xff; /* maximum bufferlength gives max info */ scb->tsb_adr = virt_to_bus(tsb); - + /*issue scb to passed ldn, and busy wait for interrupt */ got_interrupt(host_index) = 0; - issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn); + if ((scb->command & IM_OTHER_SCSI_CMD_CMD) == IM_OTHER_SCSI_CMD_CMD) + issue_cmd (host_index, virt_to_bus(scb), IM_LONG_SCB | ldn); + else + issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn); while (!got_interrupt(host_index)) barrier (); - + /*if command succesful, break */ if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED)|| (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES)) - { - return 1; - } + return 1; } - kfree(cmd); - + /*if all three retries failed, return "no device at this ldn" */ if (retries >= 3) return 0; @@ -822,25 +1048,25 @@ struct im_scb *scb; struct im_tsb *tsb; unsigned char *buf; - + scb = &(ld(host_index)[ldn].scb); tsb = &(ld(host_index)[ldn].tsb); buf = (unsigned char *)(&(ld(host_index)[ldn].buf)); ld(host_index)[ldn].tsb.dev_status = 0; - + if (bypass_controller) { /* read capacity in commonly known default SCSI-format */ cmd.cmd_len = 10; memset (&(cmd.cmnd), 0x0, sizeof(char) * cmd.cmd_len); cmd.cmnd[0] = READ_CAPACITY; /* read capacity */ - } + } for (retries = 0; retries < 3; retries++) { /*fill scb with read capacity command */ if (bypass_controller) { /* bypass the SCSI-command */ - scb->command = IM_OTHER_SCSI_CMD_CMD; - scb->enable |= IM_READ_CONTROL; + scb->command = IM_OTHER_SCSI_CMD_CMD; + scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER; scb->u1.scsi_cmd_length = cmd.cmd_len; memcpy (scb->u2.scsi_command, &(cmd.cmnd), cmd.cmd_len); last_scsi_command(host_index)[ldn] = READ_CAPACITY; @@ -849,26 +1075,27 @@ else { scb->command = IM_READ_CAPACITY_CMD; - scb->enable = IM_READ_CONTROL; + scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT; last_scsi_command(host_index)[ldn] = IM_READ_CAPACITY_CMD; - last_scsi_type(host_index)[ldn] = IM_SCB; + last_scsi_type(host_index)[ldn] = IM_SCB; } scb->sys_buf_adr = virt_to_bus(buf); scb->sys_buf_length = 8; scb->tsb_adr = virt_to_bus(tsb); - + /*issue scb to passed ldn, and busy wait for interrupt */ got_interrupt(host_index) = 0; - issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn); + if ((scb->command & IM_OTHER_SCSI_CMD_CMD) == IM_OTHER_SCSI_CMD_CMD) + issue_cmd (host_index, virt_to_bus(scb), IM_LONG_SCB | ldn); + else + issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn); while (!got_interrupt(host_index)) barrier (); - - /*if got capacity, get block length and return one device found */ + + /*if got capacity, get block length and return one device found */ if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED)|| (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES)) - { - return 1; - } + return 1; } /*if all three retries failed, return "no device at this ldn" */ if (retries >= 3) @@ -877,41 +1104,141 @@ return 1; } +static int get_pos_info(int host_index) +{ + int retries; + struct im_scb *scb; + struct im_tsb *tsb; + unsigned char *buf; + + scb = &(ld(host_index)[MAX_LOG_DEV].scb); + tsb = &(ld(host_index)[MAX_LOG_DEV].tsb); + buf = (unsigned char *)(&(ld(host_index)[MAX_LOG_DEV].buf)); + ld(host_index)[MAX_LOG_DEV].tsb.dev_status = 0; + + for (retries = 0; retries < 3; retries++) + { + /*fill scb with get_pos_info command */ + scb->command = IM_GET_POS_INFO_CMD; + scb->enable = IM_READ_CONTROL | IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE | IM_BYPASS_BUFFER | IM_SUPRESS_EXCEPTION_SHORT; + last_scsi_command(host_index)[MAX_LOG_DEV] = IM_GET_POS_INFO_CMD; + last_scsi_type(host_index)[MAX_LOG_DEV] = IM_SCB; + + scb->sys_buf_adr = virt_to_bus(buf); + if (special(host_index)==IBM_SCSI2_FW) + scb->sys_buf_length = 256; /* get all info from F/W adapter */ + else + scb->sys_buf_length = 18; /* get exactly 18 bytes for other SCSI */ + + scb->tsb_adr = virt_to_bus(tsb); + + /*issue scb to ldn=15, and busy wait for interrupt */ + got_interrupt(host_index) = 0; + issue_cmd (host_index, virt_to_bus(scb), IM_SCB | MAX_LOG_DEV); + while (!got_interrupt(host_index)) + barrier (); + + /*if got POS-stuff, get block length and return one device found */ + if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED)|| + (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES)) + return 1; + } + /* if all three retries failed, return "no device at this ldn" */ + if (retries >= 3) + return 0; + else + return 1; +} + /* SCSI-immediate-command for assign. This functions maps/unmaps specific ldn-numbers on SCSI (PUN,LUN). It is needed for presetting of the subsystem and for dynamical remapping od ldns. */ -static int immediate_assign(int host_index, unsigned int pun, - unsigned int lun, unsigned int ldn, +static int immediate_assign(int host_index, unsigned int pun, + unsigned int lun, unsigned int ldn, unsigned int operation) { int retries; unsigned long imm_command; - + for (retries=0; retries<3; retries ++) { - imm_command = inl(IM_CMD_REG(host_index)); - imm_command &= (unsigned long)(0xF8000000); /* keep reserved bits */ - imm_command |= (unsigned long)(IM_ASSIGN_IMM_CMD); - imm_command |= (unsigned long)((lun & 7) << 24); - imm_command |= (unsigned long)((operation & 1) << 23); - imm_command |= (unsigned long)((pun & 7) << 20); - imm_command |= (unsigned long)((ldn & 15) << 16); - - last_scsi_command(host_index)[0xf] = IM_ASSIGN_IMM_CMD; - last_scsi_type(host_index)[0xf] = IM_IMM_CMD; + /* select mutation level of the SCSI-adapter */ + switch (special(host_index)) + { + case IBM_SCSI2_FW: + imm_command = (unsigned long)(IM_ASSIGN_IMM_CMD); + imm_command |= (unsigned long)((lun & 7) << 24); + imm_command |= (unsigned long)((operation & 1) << 23); + imm_command |= (unsigned long)((pun & 7)<< 20)|((pun & 8)<< 24); + imm_command |= (unsigned long)((ldn & 15) << 16); + break; + default: + imm_command = inl(IM_CMD_REG(host_index)); + imm_command &= (unsigned long)(0xF8000000); /* keep reserved bits */ + imm_command |= (unsigned long)(IM_ASSIGN_IMM_CMD); + imm_command |= (unsigned long)((lun & 7) << 24); + imm_command |= (unsigned long)((operation & 1) << 23); + imm_command |= (unsigned long)((pun & 7) << 20); + imm_command |= (unsigned long)((ldn & 15) << 16); + break; + } + last_scsi_command(host_index)[MAX_LOG_DEV] = IM_ASSIGN_IMM_CMD; + last_scsi_type(host_index)[MAX_LOG_DEV] = IM_IMM_CMD; got_interrupt(host_index) = 0; - issue_cmd (host_index, (unsigned long)(imm_command), IM_IMM_CMD | 0xf); + issue_cmd (host_index, (unsigned long)(imm_command), IM_IMM_CMD | MAX_LOG_DEV); while (!got_interrupt(host_index)) barrier (); - + /*if command succesful, break */ if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED) + return 1; + } + if (retries >= 3) + return 0; + else + return 1; +} + +static int immediate_feature(int host_index, unsigned int speed, + unsigned int timeout) +{ + int retries; + unsigned long imm_command; + + for (retries=0; retries<3; retries ++) + { + /* select mutation level of the SCSI-adapter */ + switch (special(host_index)) { - return 1; + default: + imm_command = IM_FEATURE_CTR_IMM_CMD; + imm_command |= (unsigned long)((speed & 0x7) << 29); + imm_command |= (unsigned long)((timeout & 0x1fff) << 16); + break; + } + last_scsi_command(host_index)[MAX_LOG_DEV] = IM_FEATURE_CTR_IMM_CMD; + last_scsi_type(host_index)[MAX_LOG_DEV] = IM_IMM_CMD; + got_interrupt(host_index) = 0; + /* we need to run into command errors in order to probe for the + * right speed! */ + global_command_error_excuse = 1; + issue_cmd (host_index, (unsigned long)(imm_command), IM_IMM_CMD | MAX_LOG_DEV); + while (!got_interrupt(host_index)) + barrier (); + if (global_command_error_excuse == CMD_FAIL) + { + global_command_error_excuse = 0; + return 2; } + else + global_command_error_excuse = 0; + + /*if command succesful, break */ + if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED) + return 1; } - - if (retries >= 3) + + if (retries >= 3) return 0; else return 1; @@ -923,7 +1250,7 @@ int retries; int ticks; unsigned long imm_command; - + for (retries=0; retries<3; retries ++) { imm_command = inl(IM_CMD_REG(host_index)); @@ -933,31 +1260,29 @@ last_scsi_type(host_index)[ldn] = IM_IMM_CMD; got_interrupt(host_index) = 0; - reset_status(host_index) = IM_RESET_IN_PROGRESS; + reset_status(host_index) = IM_RESET_IN_PROGRESS; issue_cmd (host_index, (unsigned long)(imm_command), IM_IMM_CMD | ldn); - ticks = IM_RESET_DELAY*HZ; - while (reset_status(host_index) == IM_RESET_IN_PROGRESS && --ticks) + ticks = IM_RESET_DELAY*HZ; + while (reset_status(host_index) == IM_RESET_IN_PROGRESS && --ticks) { mdelay(1+999/HZ); barrier(); } /* if reset did not complete, just claim */ - if (!ticks) + if (!ticks) { printk("IBM MCA SCSI: reset did not complete within %d seconds.\n", IM_RESET_DELAY); - reset_status(host_index) = IM_RESET_FINISHED_OK; + reset_status(host_index) = IM_RESET_FINISHED_OK; /* did not work, finish */ return 1; } /*if command succesful, break */ if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED) - { - return 1; - } + return 1; } - - if (retries >= 3) + + if (retries >= 3) return 0; else return 1; @@ -990,17 +1315,108 @@ { const char hex[16] = "0123456789abcdef"; static char answer[2]; - + answer[1] = (char)(0x0); if (value<=MAX_LOG_DEV) answer[0] = hex[value]; else answer[0] = '-'; - + return (char *)&answer; } -/* +/* transfers bitpattern of the feature command to values in MHz */ +static char *ibmrate(unsigned int speed, int adaptertype) +{ + int i; + i=adaptertype; + switch (speed) + { + case 0: if (i) return "5.00"; else return "10.00"; break; + case 1: if (i) return "4.00"; else return "8.00"; break; + case 2: if (i) return "3.33"; else return "6.66"; break; + case 3: if (i) return "2.86"; else return "5.00"; break; + case 4: if (i) return "2.50"; else return "4.00"; break; + case 5: if (i) return "2.22"; else return "3.10"; break; + case 6: if (i) return "2.00"; else return "2.50"; break; + case 7: if (i) return "1.82"; else return "2.00"; break; + } + return "---"; +} + +static int probe_display(int what) +{ + static int rotator = 0; + const char rotor[] = "|/-\\"; + + if (!(display_mode & LED_DISP)) + return 0; + if (!what) + { + outl(0x20202020,MOD95_LED_PORT); + outl(0x20202020,MOD95_LED_PORT+4); + } + else + { + outb('S',MOD95_LED_PORT+7); + outb('C',MOD95_LED_PORT+6); + outb('S',MOD95_LED_PORT+5); + outb('I',MOD95_LED_PORT+4); + outb('i',MOD95_LED_PORT+3); + outb('n',MOD95_LED_PORT+2); + outb('i',MOD95_LED_PORT+1); + outb((char)(rotor[rotator]),MOD95_LED_PORT); + rotator++; + if (rotator>3) + rotator=0; + } + return 0; +} + +static int probe_bus_mode(int host_index) +{ + struct im_pos_info *info; + int num_bus = 0; + int ldn; + + info = (struct im_pos_info *)(&(ld(host_index)[MAX_LOG_DEV].buf)); + + if (get_pos_info(host_index)) + { + if (info->connector_size & 0xf000) + subsystem_connector_size(host_index)=16; + else + subsystem_connector_size(host_index)=32; + num_bus |= (info->pos_4b & 8) >> 3; + for (ldn=0; ldn<=MAX_LOG_DEV; ldn++) + { + if ((special(host_index)==IBM_SCSI_WCACHE)|| + (special(host_index)==IBM_7568_WCACHE)) + { + if (!((info->cache_stat >> ldn) & 1)) + ld(host_index)[ldn].cache_flag = 0; + } + if (!((info->retry_stat >> ldn) & 1)) + ld(host_index)[ldn].retry_flag = 0; + } +#ifdef IM_DEBUG_PROBE + printk("IBM MCA SCSI: SCSI-Cache bits: "); + for (ldn=0; ldn<=MAX_LOG_DEV; ldn++) + { + printk("%d",ld(host_index)[ldn].cache_flag); + } + printk("\nIBM MCA SCSI: SCSI-Retry bits: "); + for (ldn=0; ldn<=MAX_LOG_DEV; ldn++) + { + printk("%d",ld(host_index)[ldn].retry_flag); + } + printk("\n"); +#endif + } + return num_bus; +} + +/* The following routine probes the SCSI-devices in four steps: 1. The current ldn -> pun,lun mapping is removed on the SCSI-adapter. 2. ldn 0 is used to go through all possible combinations of pun,lun and @@ -1020,32 +1436,36 @@ The assignment of ALL ldns avoids dynamical remapping by the adapter itself. */ -static void check_devices (int host_index) +static void check_devices (int host_index, int adaptertype) { int id, lun, ldn, ticks; int count_devices; /* local counter for connected device */ - + int max_pun; + int num_bus; + int speedrun; /* local adapter_speed check variable */ + /* assign default values to certain variables */ - ticks = 0; count_devices = 0; IBM_DS(host_index).dyn_flag = 0; /* normally no need for dynamical ldn management */ IBM_DS(host_index).total_errors = 0; /* set errorcounter to 0 */ next_ldn(host_index) = 7; /* next ldn to be assigned is 7, because 0-6 is 'hardwired'*/ + + /* initialize the very important driver-informational arrays/structs */ + memset (ld(host_index), 0, + sizeof(ld(host_index))); for (ldn=0; ldn<=MAX_LOG_DEV; ldn++) { last_scsi_command(host_index)[ldn] = NO_SCSI; /* emptify last SCSI-command storage */ last_scsi_type(host_index)[ldn] = 0; + ld(host_index)[ldn].cache_flag = 1; + ld(host_index)[ldn].retry_flag = 1; } - - /* initialize the very important driver-informational arrays/structs */ - memset (ld(host_index), 0, - sizeof(ld(host_index))); - memset (get_ldn(host_index), TYPE_NO_DEVICE, + memset (get_ldn(host_index), TYPE_NO_DEVICE, sizeof(get_ldn(host_index))); /* this is essential ! */ memset (get_scsi(host_index), TYPE_NO_DEVICE, sizeof(get_scsi(host_index))); /* this is essential ! */ - + for (lun=0; lun<8; lun++) /* mark the adapter at its pun on all luns*/ { get_scsi(host_index)[subsystem_pun(host_index)][lun] = TYPE_IBM_SCSI_ADAPTER; @@ -1054,13 +1474,58 @@ luns. */ } + probe_display(0); /* Supercool display usage during SCSI-probing. */ + /* This makes sense, when booting without any */ + /* monitor connected on model XX95. */ + /* STEP 1: */ + adapter_speed(host_index) = global_adapter_speed; + speedrun = adapter_speed(host_index); + while (immediate_feature(host_index,speedrun,adapter_timeout)==2) + { + probe_display(1); + if (speedrun==7) + panic("IBM MCA SCSI: Cannot set Synchronous-Transfer-Rate!\n"); + speedrun++; + if (speedrun>7) + speedrun=7; + } + adapter_speed(host_index) = speedrun; + /* Get detailed information about the current adapter, necessary for + * device operations: */ + num_bus=probe_bus_mode(host_index); + + /* num_bus contains only valid data for the F/W adapter! */ + if (adaptertype==IBM_SCSI2_FW) /* F/W SCSI adapter: */ + { + /* F/W adapter PUN-space extension evaluation: */ + if (num_bus) + { + printk("IBM MCA SCSI: Seperate bus mode (wide-addressing enabled)\n"); + subsystem_maxid(host_index) = 16; + } + else + { + printk("IBM MCA SCSI: Combined bus mode (wide-addressing disabled)\n"); + subsystem_maxid(host_index) = 8; + } + printk("IBM MCA SCSI: Sync.-Rate (F/W: 20, Int.: 10, Ext.: %s) MBytes/s\n", + ibmrate(speedrun,adaptertype)); + } + else /* all other IBM SCSI adapters: */ + printk("IBM MCA SCSI: Synchronous-SCSI-Transfer-Rate: %s MBytes/s\n", + ibmrate(speedrun,adaptertype)); + + /* assign correct PUN device space */ + max_pun = subsystem_maxid(host_index); + #ifdef IM_DEBUG_PROBE printk("IBM MCA SCSI: Current SCSI-host index: %d\n",host_index); #endif printk("IBM MCA SCSI: Removing default logical SCSI-device mapping."); for (ldn=0; ldn=MAX_LOG_DEV) + if (count_devices>=MAX_LOG_DEV) IBM_DS(host_index).dyn_flag = 1; /* dynamical assignment is necessary */ - else + else IBM_DS(host_index).dyn_flag = 0; /* dynamical assignment is not necessary */ - + /* If no SCSI-devices are assigned, return 1 in order to cause message. */ if (ldn == 0) printk("IBM MCA SCSI: Warning: No SCSI-devices found/assigned!\n"); - + /* reset the counters for statistics on the current adapter */ + IBM_DS(host_index).scbs = 0; + IBM_DS(host_index).long_scbs = 0; IBM_DS(host_index).total_accesses = 0; IBM_DS(host_index).total_interrupts = 0; IBM_DS(host_index).dynamical_assignments = 0; - memset (IBM_DS(host_index).ldn_access, 0x0, + memset (IBM_DS(host_index).ldn_access, 0x0, sizeof (IBM_DS(host_index).ldn_access)); - memset (IBM_DS(host_index).ldn_read_access, 0x0, + memset (IBM_DS(host_index).ldn_read_access, 0x0, sizeof (IBM_DS(host_index).ldn_read_access)); - memset (IBM_DS(host_index).ldn_write_access, 0x0, + memset (IBM_DS(host_index).ldn_write_access, 0x0, sizeof (IBM_DS(host_index).ldn_write_access)); - memset (IBM_DS(host_index).ldn_inquiry_access, 0x0, + memset (IBM_DS(host_index).ldn_inquiry_access, 0x0, sizeof (IBM_DS(host_index).ldn_inquiry_access)); - memset (IBM_DS(host_index).ldn_modeselect_access, 0x0, + memset (IBM_DS(host_index).ldn_modeselect_access, 0x0, sizeof (IBM_DS(host_index).ldn_modeselect_access)); - memset (IBM_DS(host_index).ldn_assignments, 0x0, + memset (IBM_DS(host_index).ldn_assignments, 0x0, sizeof (IBM_DS(host_index).ldn_assignments)); - + probe_display(0); return; } /*--------------------------------------------------------------------*/ -static int device_exists (int host_index, int ldn, int *block_length, +static int device_exists (int host_index, int ldn, int *block_length, int *device_type) { unsigned char *buf; - + /* if no valid device found, return immediately with 0 */ if (!(device_inquiry(host_index, ldn))) return 0; - + buf = (unsigned char *)(&(ld(host_index)[ldn].buf)); /*if device is CD_ROM, assume block size 2048 and return */ @@ -1248,64 +1723,64 @@ *block_length = 2048; /* (standard blocksize for yellow-/red-book) */ return 1; } - - if (*buf == TYPE_WORM) /* CD-burner, WORM, Linux handles this as CD-ROM + + if (*buf == TYPE_WORM) /* CD-burner, WORM, Linux handles this as CD-ROM therefore, the block_length is also 2048. */ { *device_type = TYPE_WORM; *block_length = 2048; return 1; } - + /* if device is disk, use "read capacity" to find its block size */ if (*buf == TYPE_DISK) { *device_type = TYPE_DISK; if (read_capacity( host_index, ldn)) { - *block_length = *(buf+7) + (*(buf+6) << 8) + + *block_length = *(buf+7) + (*(buf+6) << 8) + (*(buf+5) << 16) + (*(buf+4) << 24); return 1; } else return 0; } - + /* if this is a magneto-optical drive, treat it like a harddisk */ if (*buf == TYPE_MOD) { *device_type = TYPE_MOD; if (read_capacity( host_index, ldn)) { - *block_length = *(buf+7) + (*(buf+6) << 8) + + *block_length = *(buf+7) + (*(buf+6) << 8) + (*(buf+5) << 16) + (*(buf+4) << 24); return 1; } else return 0; - } - + } + if (*buf == TYPE_TAPE) /* TAPE-device found */ { *device_type = TYPE_TAPE; *block_length = 0; /* not in use (setting by mt and mtst in op.) */ - return 1; + return 1; } - + if (*buf == TYPE_PROCESSOR) /* HP-Scanners, diverse SCSI-processing units*/ { *device_type = TYPE_PROCESSOR; *block_length = 0; /* they set their stuff on drivers */ return 1; } - + if (*buf == TYPE_SCANNER) /* other SCSI-scanners */ { *device_type = TYPE_SCANNER; *block_length = 0; /* they set their stuff on drivers */ return 1; } - + if (*buf == TYPE_MEDIUM_CHANGER) /* Medium-Changer */ { *device_type = TYPE_MEDIUM_CHANGER; @@ -1313,60 +1788,54 @@ changer device. */ return 1; } - + /* Up to now, no SCSI-devices that are known up to kernel 2.1.31 are - ignored! MO-drives are now supported and treated as harddisk. */ + ignored! MO-drives are now supported and treated as harddisk. */ return 0; } /*--------------------------------------------------------------------*/ - + #ifdef CONFIG_SCSI_IBMMCA -void ibmmca_scsi_setup (char *str, int *ints) +void internal_ibmmca_scsi_setup (char *str, int *ints) { int i, j, io_base, id_base; char *token; - + io_base = 0; id_base = 0; - + if (str) { token = strtok(str,","); j = 0; while (token) { + if (!strcmp(token,"activity")) + display_mode |= LED_ACTIVITY; if (!strcmp(token,"display")) - { - use_display = 1; - } + display_mode |= LED_DISP; if (!strcmp(token,"adisplay")) - { - use_adisplay = 1; - } + display_mode |= LED_ADISP; if (!strcmp(token,"bypass")) - { - bypass_controller = 1; - } + bypass_controller = 1; if (!strcmp(token,"normal")) - { - ibm_ansi_order = 0; - } + ibm_ansi_order = 0; if (!strcmp(token,"ansi")) - { - ibm_ansi_order = 1; - } + ibm_ansi_order = 1; + if (!strcmp(token,"fast")) + global_adapter_speed = 0; + if (!strcmp(token,"medium")) + global_adapter_speed = 4; + if (!strcmp(token,"slow")) + global_adapter_speed = 7; if ( (*token == '-') || (isdigit(*token)) ) { if (!(j%2) && (io_base < IM_MAX_HOSTS)) - { - io_port[io_base++] = simple_strtoul(token,NULL,0); - } + io_port[io_base++] = simple_strtoul(token,NULL,0); if ((j%2) && (id_base < IM_MAX_HOSTS)) - { - scsi_id[id_base++] = simple_strtoul(token,NULL,0); - } + scsi_id[id_base++] = simple_strtoul(token,NULL,0); j++; } token = strtok(NULL,","); @@ -1374,7 +1843,7 @@ } else if (ints) { - for (i = 0; i < IM_MAX_HOSTS && 2*i+2 < ints[0]; i++) + for (i = 0; i < IM_MAX_HOSTS && 2*i+2 < ints[0]; i++) { io_port[i] = ints[2*i+2]; scsi_id[i] = ints[2*i+2]; @@ -1390,28 +1859,34 @@ static int ibmmca_getinfo (char *buf, int slot, void *dev) { struct Scsi_Host *shpnt; - int len, special; + int len, speciale,connectore; unsigned int pos2, pos3; static unsigned long flags; - + +#ifdef OLDKERN + save_flags(flags); + cli(); +#else spin_lock_irqsave(&info_lock, flags); - +#endif + shpnt = dev; /* assign host-structure to local pointer */ len = 0; /* set filled text-buffer index to 0 */ /* get the _special contents of the hostdata structure */ - special = ((struct ibmmca_hostdata *)shpnt->hostdata)->_special; + speciale = ((struct ibmmca_hostdata *)shpnt->hostdata)->_special; + connectore = ((struct ibmmca_hostdata *)shpnt->hostdata)->_connector_size; pos2 = ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos2; pos3 = ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos3; - - if (special == FORCED_DETECTION) /* forced detection */ + + if (speciale == FORCED_DETECTION) /* forced detection */ { - len += sprintf (buf + len, "Adapter cathegory: forced detected\n"); + len += sprintf (buf + len, "Adapter category: forced detected\n"); len += sprintf(buf + len, "***************************************\n"); len += sprintf(buf + len, "*** Forced detected SCSI Adapter ***\n"); len += sprintf(buf + len, "*** No chip-information available ***\n"); len += sprintf(buf + len, "***************************************\n"); } - else if (special == INTEGRATED_SCSI) + else if (speciale == INTEGRATED_SCSI) { /* if the integrated subsystem has been found automatically: */ len += sprintf (buf + len, "Adapter category: integrated\n"); len += sprintf (buf + len, "Chip revision level: %d\n", @@ -1421,15 +1896,19 @@ len += sprintf (buf + len, "8 kByte NVRAM status: %s\n", (pos2 & 2) ? "locked" : "accessible"); } - else if ((special>=0)&& - (special<(sizeof(subsys_list)/sizeof(struct subsys_list_struct)))) - { /* if the subsystem is a slot adapter */ + else if ((speciale>=0)&& + (speciale<(sizeof(subsys_list)/sizeof(struct subsys_list_struct)))) + { /* if the subsystem is a slot adapter */ len += sprintf (buf + len, "Adapter category: slot-card\n"); - len += sprintf (buf + len, "Chip revision level: %d\n", - ((pos2 & 0xf0) >> 4)); + len += sprintf (buf + len, "ROM Segment Address: "); + if ((pos2 & 0xf0) == 0xf0) + len += sprintf (buf + len, "off\n"); + else + len += sprintf (buf + len, "0x%x\n", + ((pos2 & 0xf0) << 13) + 0xc0000); len += sprintf (buf + len, "Chip status: %s\n", (pos2 & 1) ? "enabled" : "disabled"); - len += sprintf (buf + len, "Port offset: 0x%x\n", + len += sprintf (buf + len, "Adapter I/O Offset: 0x%x\n", ((pos2 & 0x0e) << 2)); } else @@ -1438,10 +1917,11 @@ } /* common subsystem information to write to the slotn file */ len += sprintf (buf + len, "Subsystem PUN: %d\n", shpnt->this_id); - len += sprintf (buf + len, "I/O base address range: 0x%x-0x%x", + len += sprintf (buf + len, "I/O base address range: 0x%x-0x%x\n", (unsigned int)(shpnt->io_port), (unsigned int)(shpnt->io_port+7)); - /* Now make sure, the bufferlength is divisible by 4 to avoid + len += sprintf (buf + len, "MCA-slot size: %d bits",connectore); + /* Now make sure, the bufferlength is devidable by 4 to avoid * paging problems of the buffer. */ while ( len % sizeof( int ) != ( sizeof ( int ) - 1 ) ) { @@ -1449,34 +1929,59 @@ } len += sprintf (buf + len, "\n"); +#ifdef OLDKERN + restore_flags(flags); +#else spin_unlock_irqrestore(&info_lock, flags); +#endif return len; } - + int ibmmca_detect (Scsi_Host_Template * scsi_template) { struct Scsi_Host *shpnt; int port, id, i, j, list_size, slot; - + int devices_on_irq_11 = 0; + int devices_on_irq_14 = 0; + int IRQ14_registered = 0; + int IRQ11_registered = 0; + found = 0; /* make absolutely sure, that found is set to 0 */ + /* First of all, print the version number of the driver. This is + * important to allow better user bugreports in case of already + * having problems with the MCA_bus probing. */ + printk("IBM MCA SCSI: Version %s\n",IBMMCA_SCSI_DRIVER_VERSION); /* if this is not MCA machine, return "nothing found" */ if (!MCA_bus) { - printk("IBM MCA SCSI: No Microchannel-bus support present -> Aborting.\n"); + printk("IBM MCA SCSI: No Microchannel-bus present --> Aborting.\n"); + printk(" This machine does not have any IBM MCA-bus\n"); + printk(" or the MCA-Kernel-support is not enabled!\n"); return 0; } - else - printk("IBM MCA SCSI: Version %s\n",IBMMCA_SCSI_DRIVER_VERSION); +#ifdef MODULE + /* If the driver is run as module, read from conf.modules or cmd-line */ + if (boot_options) + option_setup(boot_options); +#endif + /* get interrupt request level */ +#ifdef OLDKERN + if (request_irq (IM_IRQ, interrupt_handler, SA_SHIRQ, "ibmmcascsi", + hosts)) +#else if (request_irq (IM_IRQ, do_interrupt_handler, SA_SHIRQ, "ibmmcascsi", hosts)) +#endif { printk("IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ); return 0; } - + else + IRQ14_registered++; + /* if ibmmcascsi setup option was passed to kernel, return "found" */ for (i = 0; i < IM_MAX_HOSTS; i++) if (io_port[i] > 0 && scsi_id[i] >= 0 && scsi_id[i] < 8) @@ -1484,20 +1989,25 @@ printk("IBM MCA SCSI: forced detected SCSI Adapter, io=0x%x, scsi id=%d.\n", io_port[i], scsi_id[i]); if ((shpnt = ibmmca_register(scsi_template, io_port[i], scsi_id[i], + FORCED_DETECTION, "forced detected SCSI Adapter"))) { ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos2 = 0; ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos3 = 0; - ((struct ibmmca_hostdata *)shpnt->hostdata)->_special = + ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos4 = 0; + ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos5 = 0; + ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos6 = 0; + ((struct ibmmca_hostdata *)shpnt->hostdata)->_special = FORCED_DETECTION; - mca_set_adapter_name(MCA_INTEGSCSI, "forcibly detected SCSI Adapter"); + mca_set_adapter_name(MCA_INTEGSCSI, "forced detected SCSI Adapter"); mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, shpnt); mca_mark_as_used(MCA_INTEGSCSI); - } + devices_on_irq_14++; + } } if (found) return found; - + /* The POS2-register of all PS/2 model SCSI-subsystems has the following * interpretation of bits: * Bit 7 - 4 : Chip Revision ID (Release) @@ -1509,16 +2019,16 @@ * Bit 4 : Reserved = 0 * Bit 3 - 0 : Reserved = 0 * (taken from "IBM, PS/2 Hardware Interface Technical Reference, Common - * Interfaces (1991)"). - * In short words, this means, that IBM PS/2 machines only support - * 1 single subsystem by default. The slot-adapters must have another + * Interfaces (1991)"). + * In short words, this means, that IBM PS/2 machines only support + * 1 single subsystem by default. The slot-adapters must have another * configuration on pos2. Here, one has to assume the following * things for POS2-register: * Bit 7 - 4 : Chip Revision ID (Release) * Bit 3 - 1 : port offset factor * Bit 0 : Chip Enable (EN-Signal) * As I found a patch here, setting the IO-registers to 0x3540 forced, - * as there was a 0x05 in POS2 on a model 56, I assume, that the + * as there was a 0x05 in POS2 on a model 56, I assume, that the * port 0x3540 must be fix for integrated SCSI-controllers. * Ok, this discovery leads to the following implementation: (M.Lang) */ @@ -1526,13 +2036,15 @@ for (j=0;j<8;j++) /* read the pos-information */ pos[j] = mca_read_stored_pos(MCA_INTEGSCSI,j); /* pos2 = pos3 = 0xff if there is no integrated SCSI-subsystem present */ - if (( pos[2] != 0xff) || (pos[3] != 0xff )) + /* if (( pos[2] != 0xff) || (pos[3] != 0xff )) */ + /* Previous if-arguments do fail! Therefore, we use now the following to + * make sure, we see a real integrated onboard SCSI-interface: */ + if ((!pos[0] && !pos[1] && pos[2]>0 && pos[3]>0 && !pos[4] && !pos[5] && !pos[6] && !pos[7]) || + (pos[0]==0xff && pos[1]==0xff && pos[2]<0xff && pos[3]<0xff && pos[4]==0xff && pos[5]==0xff && pos[6]==0xff && pos[7]==0xff)) { if ((pos[2] & 1) == 1) /* is the subsystem chip enabled ? */ - { - port = IM_IO_PORT; - } - else + port = IM_IO_PORT; + else { /* if disabled, no IRQs will be generated, as the chip won't * listen to the incomming commands and will do really nothing, * except for listening to the pos-register settings. If this @@ -1543,10 +2055,10 @@ port = IM_IO_PORT; /* anyway, set the portnumber and warn */ printk("IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n"); printk(" SCSI-operations may not work.\n"); - } + } id = (pos[3] & 0xe0) >> 5; /* this is correct and represents the PUN */ - - /* give detailed information on the subsystem. This helps me + + /* give detailed information on the subsystem. This helps me * additionally during debugging and analyzing bug-reports. */ printk("IBM MCA SCSI: IBM Integrated SCSI Controller found, io=0x%x, scsi id=%d,\n", port, id); @@ -1556,20 +2068,25 @@ /* register the found integrated SCSI-subsystem */ if ((shpnt = ibmmca_register(scsi_template, port, id, + INTEGRATED_SCSI, "IBM Integrated SCSI Controller"))) { ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos2 = pos[2]; ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos3 = pos[3]; - ((struct ibmmca_hostdata *)shpnt->hostdata)->_special = + ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos4 = pos[4]; + ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos5 = pos[5]; + ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos6 = pos[6]; + ((struct ibmmca_hostdata *)shpnt->hostdata)->_special = INTEGRATED_SCSI; mca_set_adapter_name(MCA_INTEGSCSI, "IBM Integrated SCSI Controller"); mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, shpnt); mca_mark_as_used(MCA_INTEGSCSI); + devices_on_irq_14++; } } - - /* now look for other adapters in MCA slots, */ + + /* now look for other adapters in MCA slots, */ /* determine the number of known IBM-SCSI-subsystem types */ /* see the pos[2] dependence to get the adapter port-offset. */ list_size = sizeof(subsys_list) / sizeof(struct subsys_list_struct); @@ -1584,54 +2101,189 @@ if ((pos[2] & 1) == 1) /* is the subsystem chip enabled ? */ { /* (explanations see above) */ port = IM_IO_PORT + ((pos[2] & 0x0e) << 2); - } - else + } + else { /* anyway, set the portnumber and warn */ - port = IM_IO_PORT + ((pos[2] & 0x0e) << 2); + port = IM_IO_PORT + ((pos[2] & 0x0e) << 2); printk("IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n"); printk(" SCSI-operations may not work.\n"); + } + if ((i==IBM_SCSI2_FW)&&(pos[6]!=0)) + { + printk("IBM MCA SCSI: ERROR - Wrong POS(6)-register setting!\n"); + printk(" Impossible to determine adapter PUN!\n"); + printk(" Guessing adapter PUN = 7.\n"); + id = 7; + } + else + { + id = (pos[3] & 0xe0) >> 5; /* get subsystem PUN */ + if (i==IBM_SCSI2_FW) + { + id |= (pos[3] & 0x10) >> 1; /* get subsystem PUN high-bit + * for F/W adapters */ + } + } + if ((i==IBM_SCSI2_FW)&&(pos[4] & 0x01)&&(pos[6]==0)) + { /* IRQ11 is used by SCSI-2 F/W Adapter/A */ + printk("IBM MCA SCSI: SCSI-2 F/W adapter needs IRQ 11.\n"); + /* get interrupt request level */ +#ifdef OLDKERN + if (request_irq (IM_IRQ_FW, interrupt_handler, SA_SHIRQ, + "ibmmcascsi", hosts)) +#else + if (request_irq (IM_IRQ_FW, do_interrupt_handler, SA_SHIRQ, + "ibmmcascsi", hosts)) +#endif + { + printk("IBM MCA SCSI: Unable to get shared IRQ %d.\n", + IM_IRQ_FW); + } + else + IRQ11_registered++; } - id = (pos[3] & 0xe0) >> 5; /* get subsystem PUN */ printk("IBM MCA SCSI: %s found in slot %d, io=0x%x, scsi id=%d,\n", subsys_list[i].description, slot + 1, port, id); - printk(" chip rev.=%d, port-offset=0x%x, subsystem=%s\n", - ((pos[2] & 0xf0) >> 4), + if ((pos[2] & 0xf0) == 0xf0) + printk(" ROM Addr.=off,"); + else + printk(" ROM Addr.=0x%x,", + ((pos[2] & 0xf0) << 13) + 0xc0000); + printk(" port-offset=0x%x, subsystem=%s\n", ((pos[2] & 0x0e) << 2), (pos[2] & 1) ? "enabled." : "disabled."); - + /* register the hostadapter */ - if ((shpnt = ibmmca_register(scsi_template, port, id, + if ((shpnt = ibmmca_register(scsi_template, port, id, i, subsys_list[i].description))) { ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos2 = pos[2]; ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos3 = pos[3]; + ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos4 = pos[4]; + ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos5 = pos[5]; + ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos6 = pos[6]; ((struct ibmmca_hostdata *)shpnt->hostdata)->_special = i; mca_set_adapter_name (slot, subsys_list[i].description); mca_set_adapter_procfn (slot, (MCA_ProcFn) ibmmca_getinfo, shpnt); mca_mark_as_used(slot); + if ((i==IBM_SCSI2_FW)&&(pos[4] & 0x01)&&(pos[6]==0)) + devices_on_irq_11++; + else + devices_on_irq_14++; } slot++; /* advance to next slot */ } /* advance to next adapter id in the list of IBM-SCSI-subsystems*/ } - if (!found) - { /* maybe ESDI, or other producers' SCSI-hosts */ - free_irq (IM_IRQ, hosts); - printk("IBM MCA SCSI: No IBM SCSI-subsystem adapter attached.\n"); + + /* now look for SCSI-adapters, by bugs mapped to the integrated SCSI + * area. E.g. a W/Cache in MCA-slot 9 ???? Arrrrgh!! */ + list_size = sizeof(subsys_list) / sizeof(struct subsys_list_struct); + for (i = 0; i < list_size; i++) + { /* scan each slot for a fitting adapter id */ + slot = mca_find_adapter(subsys_list[i].mca_id, MCA_INTEGSCSI); + if (slot != MCA_NOTFOUND) + { /* scan through all slots */ + for (j=0;j<8;j++) /* read the pos-information */ + pos[j] = mca_read_stored_pos(slot, j); + if ((pos[2] & 1) == 1) /* is the subsystem chip enabled ? */ + { /* (explanations see above) */ + port = IM_IO_PORT + ((pos[2] & 0x0e) << 2); + } + else + { /* anyway, set the portnumber and warn */ + port = IM_IO_PORT + ((pos[2] & 0x0e) << 2); + printk("IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n"); + printk(" SCSI-operations may not work.\n"); + } + if ((i==IBM_SCSI2_FW)&&(pos[6]!=0)) + { + printk("IBM MCA SCSI: ERROR - Wrong POS(6)-register setting!\n"); + printk(" Impossible to determine adapter PUN!\n"); + printk(" Guessing adapter PUN = 7.\n"); + id = 7; + } + else + { + id = (pos[3] & 0xe0) >> 5; /* get subsystem PUN */ + if (i==IBM_SCSI2_FW) + { + id |= (pos[3] & 0x10) >> 1; /* get subsystem PUN high-bit + * for F/W adapters */ + } + } + if ((i==IBM_SCSI2_FW)&&(pos[4] & 0x01)&&(pos[6]==0)) + { /* IRQ11 is used by SCSI-2 F/W Adapter/A */ + printk("IBM MCA SCSI: SCSI-2 F/W adapter needs IRQ 11.\n"); + /* get interrupt request level */ +#ifdef OLDKERN + if (request_irq (IM_IRQ_FW, interrupt_handler, SA_SHIRQ, + "ibmmcascsi", hosts)) +#else + if (request_irq (IM_IRQ_FW, do_interrupt_handler, SA_SHIRQ, + "ibmmcascsi", hosts)) +#endif + { + printk("IBM MCA SCSI: Unable to get shared IRQ %d.\n", + IM_IRQ_FW); + } + else + IRQ11_registered++; + } + printk("IBM MCA SCSI: %s found in slot %d, io=0x%x, scsi id=%d,\n", + subsys_list[i].description, slot + 1, port, id); + if ((pos[2] & 0xf0) == 0xf0) + printk(" ROM Addr.=off,"); + else + printk(" ROM Addr.=0x%x,", + ((pos[2] & 0xf0) << 13) + 0xc0000); + printk(" port-offset=0x%x, subsystem=%s\n", + ((pos[2] & 0x0e) << 2), + (pos[2] & 1) ? "enabled." : "disabled."); + + /* register the hostadapter */ + if ((shpnt = ibmmca_register(scsi_template, port, id, i, + subsys_list[i].description))) + { + ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos2 = pos[2]; + ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos3 = pos[3]; + ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos4 = pos[4]; + ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos5 = pos[5]; + ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos6 = pos[6]; + ((struct ibmmca_hostdata *)shpnt->hostdata)->_special = i; + + mca_set_adapter_name (slot, subsys_list[i].description); + mca_set_adapter_procfn (slot, (MCA_ProcFn) ibmmca_getinfo, + shpnt); + mca_mark_as_used(slot); + if ((i==IBM_SCSI2_FW)&&(pos[4] & 0x01)&&(pos[6]==0)) + devices_on_irq_11++; + else + devices_on_irq_14++; + } + slot++; /* advance to next slot */ + } /* advance to next adapter id in the list of IBM-SCSI-subsystems*/ } + + if ( IRQ11_registered && !devices_on_irq_11 ) + free_irq(IM_IRQ_FW, hosts); /* no devices on IRQ 11 */ + if ( IRQ14_registered && !devices_on_irq_14 ) + free_irq(IM_IRQ, hosts); /* no devices on IRQ 14 */ + if ( !devices_on_irq_11 && !devices_on_irq_14 ) + printk("IBM MCA SCSI: No IBM SCSI-subsystem adapter attached.\n"); return found; /* return the number of found SCSI hosts. Should be 1 or 0. */ } static struct Scsi_Host * -ibmmca_register(Scsi_Host_Template * scsi_template, int port, int id, - char *hostname) +ibmmca_register(Scsi_Host_Template * scsi_template, int port, int id, + int adaptertype, char *hostname) { struct Scsi_Host *shpnt; int i, j; unsigned int ctrl; - + /* check I/O region */ if (check_region(port, IM_N_IO_PORT)) { @@ -1639,7 +2291,7 @@ port, port + IM_N_IO_PORT - 1, IM_N_IO_PORT); return NULL; } - + /* register host */ shpnt = scsi_register(scsi_template, sizeof(struct ibmmca_hostdata)); if (!shpnt) @@ -1647,18 +2299,21 @@ printk("IBM MCA SCSI: Unable to register host.\n"); return NULL; } - + /* request I/O region */ request_region(port, IM_N_IO_PORT, hostname); - + hosts[found] = shpnt; /* add new found hostadapter to the list */ + special(found) = adaptertype; /* important assignment or else crash! */ + subsystem_connector_size(found) = 0; /* preset slot-size */ shpnt->irq = IM_IRQ; /* assign necessary stuff for the adapter */ shpnt->io_port = port; shpnt->n_io_port = IM_N_IO_PORT; shpnt->this_id = id; + shpnt->max_id = 8; /* 8 PUNs are default */ /* now, the SCSI-subsystem is connected to Linux */ - - ctrl = (unsigned int)(inb(IM_CTR_REG(found))); /* get control-register status */ + + ctrl = (unsigned int)(inb(IM_CTR_REG(found))); /* get control-register status */ #ifdef IM_DEBUG_PROBE printk("IBM MCA SCSI: Control Register contents: %x, status: %x\n", ctrl,inb(IM_STAT_REG(found))); @@ -1669,18 +2324,19 @@ if (bypass_controller) printk("IBM MCA SCSI: Subsystem SCSI-commands get bypassed.\n"); #endif - + reset_status(found) = IM_RESET_NOT_IN_PROGRESS; - for (i = 0; i < 8; i++) /* reset the tables */ + for (i = 0; i < 16; i++) /* reset the tables */ for (j = 0; j < 8; j++) get_ldn(found)[i][j] = MAX_LOG_DEV; /* check which logical devices exist */ - local_checking_phase_flag(found) = 1; - check_devices(found); /* call by value, using the global variable hosts*/ + /* after this line, local interrupting is possible: */ + local_checking_phase_flag(found) = 1; + check_devices(found,adaptertype); /* call by value, using the global variable hosts*/ local_checking_phase_flag(found) = 0; - + found++; /* now increase index to be prepared for next found subsystem */ /* an ibm mca subsystem has been detected */ return shpnt; @@ -1710,21 +2366,21 @@ /*--------------------------------------------------------------------*/ /* The following routine is the SCSI command queue. The old edition is - now improved by dynamical reassignment of ldn numbers that are + now improved by dynamical reassignment of ldn numbers that are currently not assigned. The mechanism works in a way, that first the physical structure is checked. If at a certain pun,lun a device should be present, the routine proceeds to the ldn check from get_ldn. An answer of 0xff would show-up, that the aimed device is - currently not assigned any ldn. At this point, the dynamical + currently not assigned any ldn. At this point, the dynamical remapping algorithm is called. It works in a way, that it goes in cyclic order through the ldns from 7 to 14. If a ldn is assigned, it takes 8 dynamical reassignment calls, until a device looses its - ldn again. With this method it is assured, that while doing + ldn again. With this method it is assured, that while doing intense I/O between up to eight devices, no dynamical remapping is done there. ldns 0 through 6(!) are left untouched, which means, that puns 0 through 7(!) on lun=0 are always accessible without remapping. - These ldns are statically assigned by this driver. The subsystem always - occupies at least one pun, therefore 7 ldns (at lun=0) for other devices + These ldns are statically assigned by this driver. The subsystem always + occupies at least one pun, therefore 7 ldns (at lun=0) for other devices are sufficient. (The adapter uses always ldn=15, at whatever pun it is.) */ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) { @@ -1736,33 +2392,46 @@ int id,lun; int target; int host_index; - - if (ibm_ansi_order) - target = 6 - cmd->target; - else - target = cmd->target; - + int max_pun; + int i; + struct scatterlist *sl; + shpnt = cmd->host; /* search for the right hostadapter */ for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++); - + if (!hosts[host_index]) { /* invalid hostadapter descriptor address */ cmd->result = DID_NO_CONNECT << 16; - done (cmd); + if (done) + done (cmd); return 0; } - + + max_pun = subsystem_maxid(host_index); + + if (ibm_ansi_order) + { + target = max_pun - 1 - cmd->target; + if ((target <= subsystem_pun(host_index))&&(cmd->target <= subsystem_pun(host_index))) + target--; + else if ((target >= subsystem_pun(host_index))&&(cmd->target >= subsystem_pun(host_index))) + target++; + } + else + target = cmd->target; + /*if (target,lun) is NO LUN or not existing at all, return error */ if ((get_scsi(host_index)[target][cmd->lun] == TYPE_NO_LUN)|| (get_scsi(host_index)[target][cmd->lun] == TYPE_NO_DEVICE)) { cmd->result = DID_NO_CONNECT << 16; - done (cmd); + if (done) + done (cmd); return 0; } - + /*if (target,lun) unassigned, do further checks... */ ldn = get_ldn(host_index)[target][cmd->lun]; if (ldn >= MAX_LOG_DEV) /* on invalid ldn do special stuff */ @@ -1773,7 +2442,7 @@ while (ld(host_index)[next_ldn(host_index)].cmd) /* search for a occupied, but not in */ { /* command-processing ldn. */ next_ldn(host_index)++; - if (next_ldn(host_index)>=MAX_LOG_DEV) + if (next_ldn(host_index)>=MAX_LOG_DEV) next_ldn(host_index) = 7; if (current_ldn == next_ldn(host_index)) /* One circle done ? */ { /* no non-processing ldn found */ @@ -1782,18 +2451,19 @@ printk(" Reporting DID_NO_CONNECT for device (%d,%d).\n", target, cmd->lun); cmd->result = DID_NO_CONNECT << 16;/* return no connect*/ - done (cmd); + if (done) + done (cmd); return 0; } } - + /* unmap non-processing ldn */ - for (id=0; id<8; id ++) + for (id=0; idlun); - + /* set back to normal interrupt_handling */ local_checking_phase_flag(host_index) = 0; - + /* Information on syslog terminal */ printk("IBM MCA SCSI: ldn=0x%x dynamically reassigned to (%d,%d).\n", ldn, target, cmd->lun); - - /* increase next_ldn for next dynamical assignment */ + + /* increase next_ldn for next dynamical assignment */ next_ldn(host_index)++; - if (next_ldn(host_index)>=MAX_LOG_DEV) + if (next_ldn(host_index)>=MAX_LOG_DEV) next_ldn(host_index) = 7; - } + } else - { /* wall against Linux accesses to the subsystem adapter */ + { /* wall against Linux accesses to the subsystem adapter */ cmd->result = DID_BAD_TARGET << 16; - done (cmd); + if (done) + done (cmd); return 0; } } - + /*verify there is no command already in progress for this log dev */ if (ld(host_index)[ldn].cmd) panic ("IBM MCA SCSI: cmd already in progress for this ldn.\n"); - + /*save done in cmd, and save cmd for the interrupt handler */ cmd->scsi_done = done; ld(host_index)[ldn].cmd = cmd; - + /*fill scb information independent of the scsi command */ scb = &(ld(host_index)[ldn].scb); ld(host_index)[ldn].tsb.dev_status = 0; - scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR; + scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE; scb->tsb_adr = virt_to_bus(&(ld(host_index)[ldn].tsb)); + scsi_cmd = cmd->cmnd[0]; + if (cmd->use_sg) { - int i = cmd->use_sg; - struct scatterlist *sl = (struct scatterlist *) cmd->request_buffer; + i = cmd->use_sg; + sl = (struct scatterlist *)(cmd->request_buffer); if (i > 16) panic ("IBM MCA SCSI: scatter-gather list too long.\n"); while (--i >= 0) { - ld(host_index)[ldn].sge[i].address = (void *) virt_to_bus(sl[i].address); + ld(host_index)[ldn].sge[i].address = (void *)(virt_to_bus(sl[i].address)); ld(host_index)[ldn].sge[i].byte_length = sl[i].length; } scb->enable |= IM_POINTER_TO_LIST; @@ -1877,31 +2550,45 @@ else { scb->sys_buf_adr = virt_to_bus(cmd->request_buffer); - scb->sys_buf_length = cmd->request_bufflen; + /* recent Linux midlevel SCSI places 1024 byte for inquiry + * command. Far too much for old PS/2 hardware. */ + switch (scsi_cmd) + { /* avoid command errors by setting bufferlengths to + * ANSI-standard. */ + case INQUIRY: + case REQUEST_SENSE: + case MODE_SENSE: + case MODE_SELECT: + scb->sys_buf_length = 255; + break; + case TEST_UNIT_READY: + scb->sys_buf_length = 0; + break; + default: + scb->sys_buf_length = cmd->request_bufflen; + break; + } } - /*fill scb information dependent on scsi command */ - scsi_cmd = cmd->cmnd[0]; - + #ifdef IM_DEBUG_CMD printk("issue scsi cmd=%02x to ldn=%d\n", scsi_cmd, ldn); #endif - + /* for specific device-type debugging: */ #ifdef IM_DEBUG_CMD_SPEC_DEV if (ld(host_index)[ldn].device_type==IM_DEBUG_CMD_DEVICE) - printk("(SCSI-device-type=0x%x) issue scsi cmd=%02x to ldn=%d\n", + printk("(SCSI-device-type=0x%x) issue scsi cmd=%02x to ldn=%d\n", ld(host_index)[ldn].device_type, scsi_cmd, ldn); #endif - + /* for possible panics store current command */ - last_scsi_command(host_index)[ldn] = scsi_cmd; - last_scsi_type(host_index)[ldn] = IM_SCB; - + last_scsi_command(host_index)[ldn] = scsi_cmd; + last_scsi_type(host_index)[ldn] = IM_SCB; /* update statistical info */ IBM_DS(host_index).total_accesses++; IBM_DS(host_index).ldn_access[ldn]++; - + switch (scsi_cmd) { case READ_6: @@ -1909,54 +2596,48 @@ case READ_10: case WRITE_10: case READ_12: - case WRITE_12: - /* statistics for proc_info */ - if ((scsi_cmd == READ_6)||(scsi_cmd == READ_10)||(scsi_cmd == READ_12)) - IBM_DS(host_index).ldn_read_access[ldn]++; /* increase READ-access on ldn stat. */ - else if ((scsi_cmd == WRITE_6)||(scsi_cmd == WRITE_10)|| - (scsi_cmd == WRITE_12)) - IBM_DS(host_index).ldn_write_access[ldn]++; /* increase write-count on ldn stat.*/ - + case WRITE_12: /* Distinguish between disk and other devices. Only disks (that are the - most frequently accessed devices) should be supported by the - IBM-SCSI-Subsystem commands. */ + most frequently accessed devices) should be supported by the + IBM-SCSI-Subsystem commands. */ switch (ld(host_index)[ldn].device_type) { case TYPE_DISK: /* for harddisks enter here ... */ case TYPE_MOD: /* ... try it also for MO-drives (send flames as */ /* you like, if this won't work.) */ - if (scsi_cmd == READ_6 || scsi_cmd == READ_10 || + if (scsi_cmd == READ_6 || scsi_cmd == READ_10 || scsi_cmd == READ_12) { /* read command preparations */ + scb->enable |= IM_READ_CONTROL; + IBM_DS(host_index).ldn_read_access[ldn]++; /* increase READ-access on ldn stat. */ if (bypass_controller) { scb->command = IM_OTHER_SCSI_CMD_CMD; - scb->enable |= IM_READ_CONTROL; + scb->enable |= IM_BYPASS_BUFFER; scb->u1.scsi_cmd_length = cmd->cmd_len; memcpy(scb->u2.scsi_command,cmd->cmnd,cmd->cmd_len); + last_scsi_type(host_index)[ldn] = IM_LONG_SCB; } else - { - scb->command = IM_READ_DATA_CMD; - scb->enable |= IM_READ_CONTROL; - } + scb->command = IM_READ_DATA_CMD | IM_NO_DISCONNECT; } else { /* write command preparations */ + IBM_DS(host_index).ldn_write_access[ldn]++; /* increase write-count on ldn stat.*/ if (bypass_controller) { scb->command = IM_OTHER_SCSI_CMD_CMD; + scb->enable |= IM_BYPASS_BUFFER; scb->u1.scsi_cmd_length = cmd->cmd_len; memcpy(scb->u2.scsi_command,cmd->cmnd,cmd->cmd_len); + last_scsi_type(host_index)[ldn] = IM_LONG_SCB; } else - { - scb->command = IM_WRITE_DATA_CMD; - } + scb->command = IM_WRITE_DATA_CMD | IM_NO_DISCONNECT; } - + if (!bypass_controller) - { + { if (scsi_cmd == READ_6 || scsi_cmd == WRITE_6) { scb->u1.log_blk_adr = (((unsigned) cmd->cmnd[3]) << 0) | @@ -1973,12 +2654,14 @@ scb->u2.blk.count = (((unsigned) cmd->cmnd[8]) << 0) | (((unsigned) cmd->cmnd[7]) << 8); } + last_scsi_logical_block(host_index)[ldn] = scb->u1.log_blk_adr; + last_scsi_blockcount(host_index)[ldn] = scb->u2.blk.count; scb->u2.blk.length = ld(host_index)[ldn].block_length; - } + } if (++disk_rw_in_progress == 1) PS2_DISK_LED_ON (shpnt->host_no, target); break; - + /* for other devices, enter here. Other types are not known by Linux! TYPE_NO_LUN is forbidden as valid device. */ case TYPE_ROM: @@ -1986,31 +2669,29 @@ case TYPE_PROCESSOR: case TYPE_WORM: case TYPE_SCANNER: - case TYPE_MEDIUM_CHANGER: - + case TYPE_MEDIUM_CHANGER: /* If there is a sequential-device, IBM recommends to use - IM_OTHER_SCSI_CMD_CMD instead of subsystem READ/WRITE. + IM_OTHER_SCSI_CMD_CMD instead of subsystem READ/WRITE. Good/modern CD-ROM-drives are capable of reading sequential AND random-access. This leads to the problem, - that random-accesses are covered by the subsystem, but + that random-accesses are covered by the subsystem, but sequentials are not, as like for tape-drives. Therefore, it is the easiest way to use IM_OTHER_SCSI_CMD_CMD for all read-ops on CD-ROM-drives in order not to run into timing problems and to have a stable state. In addition, data-access on CD-ROMs works faster like that. Strange, but obvious. */ - + scb->command = IM_OTHER_SCSI_CMD_CMD; - if (scsi_cmd == READ_6 || scsi_cmd == READ_10 || + if (scsi_cmd == READ_6 || scsi_cmd == READ_10 || scsi_cmd == READ_12) /* enable READ */ - { - scb->enable |= IM_READ_CONTROL; - } - + scb->enable |= IM_READ_CONTROL; + scb->enable |= IM_BYPASS_BUFFER; scb->u1.scsi_cmd_length = cmd->cmd_len; memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len); - - /* Read/write on this non-disk devices is also displayworthy, - so flash-up the LED/display. */ + last_scsi_type(host_index)[ldn] = IM_LONG_SCB; + + /* Read/write on this non-disk devices is also displayworthy, + so flash-up the LED/display. */ if (++disk_rw_in_progress == 1) PS2_DISK_LED_ON (shpnt->host_no, target); break; @@ -2021,17 +2702,27 @@ if (bypass_controller) { scb->command = IM_OTHER_SCSI_CMD_CMD; - scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT; + scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER; + scb->u1.log_blk_adr = 0; scb->u1.scsi_cmd_length = cmd->cmd_len; memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len); + last_scsi_type(host_index)[ldn] = IM_LONG_SCB; } else { scb->command = IM_DEVICE_INQUIRY_CMD; scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT; + scb->u1.log_blk_adr = 0; } break; - + case TEST_UNIT_READY: + scb->command = IM_OTHER_SCSI_CMD_CMD; + scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER; + scb->u1.log_blk_adr = 0; + scb->u1.scsi_cmd_length = 6; + memcpy (scb->u2.scsi_command, cmd->cmnd, 6); + last_scsi_type(host_index)[ldn] = IM_LONG_SCB; + break; case READ_CAPACITY: /* the length of system memory buffer must be exactly 8 bytes */ if (scb->sys_buf_length > 8) @@ -2039,55 +2730,67 @@ if (bypass_controller) { scb->command = IM_OTHER_SCSI_CMD_CMD; - scb->enable |= IM_READ_CONTROL; + scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER; scb->u1.scsi_cmd_length = cmd->cmd_len; memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len); + last_scsi_type(host_index)[ldn] = IM_LONG_SCB; } else { scb->command = IM_READ_CAPACITY_CMD; - scb->enable |= IM_READ_CONTROL; + scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT; } break; - - /* Commands that need read-only-mode (system <- device): */ + + /* Commands that need read-only-mode (system <- device): */ case REQUEST_SENSE: - if (bypass_controller) + if (bypass_controller) { scb->command = IM_OTHER_SCSI_CMD_CMD; - scb->enable |= IM_READ_CONTROL; + scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER; scb->u1.scsi_cmd_length = cmd->cmd_len; memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len); + last_scsi_type(host_index)[ldn] = IM_LONG_SCB; } else { scb->command = IM_REQUEST_SENSE_CMD; - scb->enable |= IM_READ_CONTROL; + scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT; } break; - - /* Commands that need write-only-mode (system -> device): */ + + /* Commands that need write-only-mode (system -> device): */ case MODE_SELECT: case MODE_SELECT_10: IBM_DS(host_index).ldn_modeselect_access[ldn]++; - scb->command = IM_OTHER_SCSI_CMD_CMD; - scb->enable |= IM_SUPRESS_EXCEPTION_SHORT; /*Select needs WRITE-enabled*/ + scb->command = IM_OTHER_SCSI_CMD_CMD; + scb->enable |= IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER; /*Select needs WRITE-enabled*/ scb->u1.scsi_cmd_length = cmd->cmd_len; memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len); + last_scsi_type(host_index)[ldn] = IM_LONG_SCB; break; - - /* For other commands, read-only is useful. Most other commands are + + /* For other commands, read-only is useful. Most other commands are running without an input-data-block. */ default: scb->command = IM_OTHER_SCSI_CMD_CMD; - scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT; + scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER; scb->u1.scsi_cmd_length = cmd->cmd_len; memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len); + last_scsi_type(host_index)[ldn] = IM_LONG_SCB; break; } - /*issue scb command, and return */ - issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn); + if (last_scsi_type(host_index)[ldn] == IM_LONG_SCB) + { + issue_cmd (host_index, virt_to_bus(scb), IM_LONG_SCB | ldn); + IBM_DS(host_index).long_scbs++; + } + else + { + issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn); + IBM_DS(host_index).scbs++; + } return 0; } @@ -2098,36 +2801,50 @@ /* Abort does not work, as the adapter never generates an interrupt on * whatever situation is simulated, even when really pending commands * are running on the adapters' hardware ! */ - + struct Scsi_Host *shpnt; unsigned int ldn; void (*saved_done) (Scsi_Cmnd *); int target; int host_index; + int max_pun; static unsigned long flags; unsigned long imm_command; /* return SCSI_ABORT_SNOOZE ; */ +#ifdef OLDKERN + save_flags(flags); + cli(); +#else spin_lock_irqsave(&abort_lock, flags); - if (ibm_ansi_order) - target = 6 - cmd->target; - else - target = cmd->target; - +#endif shpnt = cmd->host; /* search for the right hostadapter */ - for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++); - + for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++); + if (!hosts[host_index]) { /* invalid hostadapter descriptor address */ cmd->result = DID_NO_CONNECT << 16; if (cmd->scsi_done) - (cmd->done) (cmd); + (cmd->scsi_done) (cmd); return SCSI_ABORT_SNOOZE; } - + + max_pun = subsystem_maxid(host_index); + + if (ibm_ansi_order) + { + target = max_pun - 1 - cmd->target; + if ((target <= subsystem_pun(host_index))&&(cmd->target <= subsystem_pun(host_index))) + target--; + else if ((target >= subsystem_pun(host_index))&&(cmd->target >= subsystem_pun(host_index))) + target++; + } + else + target = cmd->target; + /*get logical device number, and disable system interrupts */ printk ("IBM MCA SCSI: Sending abort to device pun=%d, lun=%d.\n", target, cmd->lun); @@ -2136,13 +2853,17 @@ /*if cmd for this ldn has already finished, no need to abort */ if (!ld(host_index)[ldn].cmd) { +#ifdef OLDKERN + restore_flags(flags); +#else spin_unlock_irqrestore(&abort_lock, flags); +#endif return SCSI_ABORT_NOT_RUNNING; } - /* Clear ld.cmd, save done function, install internal done, - * send abort immediate command (this enables sys. interrupts), - * and wait until the interrupt arrives. + /* Clear ld.cmd, save done function, install internal done, + * send abort immediate command (this enables sys. interrupts), + * and wait until the interrupt arrives. */ saved_done = cmd->scsi_done; cmd->scsi_done = internal_done; @@ -2157,22 +2878,34 @@ { if (!(inb (IM_STAT_REG(host_index)) & IM_BUSY)) break; +#ifdef OLDKERN + restore_flags (flags); +#else spin_unlock_irqrestore(&abort_lock, flags); - +#endif +#ifdef OLDKERN + save_flags(flags); + cli(); +#else spin_lock_irqsave(&abort_lock, flags); +#endif } /*write registers and enable system interrupts */ outl (imm_command, IM_CMD_REG(host_index)); outb (IM_IMM_CMD | ldn, IM_ATTN_REG(host_index)); +#ifdef OLDKERN + restore_flags (flags); +#else spin_unlock_irqrestore(&abort_lock, flags); - +#endif + #ifdef IM_DEBUG_PROBE printk("IBM MCA SCSI: Abort submitted, waiting for adapter response...\n"); -#endif +#endif while (!cmd->SCp.Status) - barrier (); - cmd->scsi_done = saved_done; - /*if abort went well, call saved done, then return success or error */ + barrier (); + cmd->scsi_done = saved_done; + /*if abort went well, call saved done, then return success or error */ if (cmd->result == (DID_ABORT << 16)) { cmd->result |= DID_ABORT << 16; @@ -2181,7 +2914,7 @@ ld(host_index)[ldn].cmd = NULL; #ifdef IM_DEBUG_PROBE printk("IBM MCA SCSI: Abort finished with success.\n"); -#endif +#endif return SCSI_ABORT_SUCCESS; } else @@ -2192,7 +2925,7 @@ ld(host_index)[ldn].cmd = NULL; #ifdef IM_DEBUG_PROBE printk("IBM MCA SCSI: Abort failed.\n"); -#endif +#endif return SCSI_ABORT_ERROR; } } @@ -2208,7 +2941,17 @@ static unsigned long flags; unsigned long imm_command; + if (cmd == NULL) + { + printk("IBM MCA SCSI: Reset called with NULL-command!\n"); + return(SCSI_RESET_SNOOZE); + } +#ifdef OLDKERN + save_flags(flags); + cli(); +#else spin_lock_irqsave(&reset_lock, flags); +#endif ticks = IM_RESET_DELAY*HZ; shpnt = cmd->host; /* search for the right hostadapter */ @@ -2218,9 +2961,19 @@ { /* invalid hostadapter descriptor address */ if (!local_checking_phase_flag(host_index)) { - cmd->result = DID_NO_CONNECT << 16; - if (cmd->scsi_done) - (cmd->done) (cmd); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,132) + if (flags & SCSI_RESET_SYNCHRONOUS) + { +#ifdef OLDKERN + restore_flags(flags); +#else + spin_unlock_irqrestore(&reset_lock, flags); +#endif + cmd->result = DID_NO_CONNECT << 16; + if (cmd->scsi_done) + (cmd->scsi_done) (cmd); + } +#endif } return SCSI_ABORT_SNOOZE; } @@ -2228,7 +2981,11 @@ if (local_checking_phase_flag(host_index)) { printk("IBM MCA SCSI: unable to reset while checking devices.\n"); +#ifdef OLDKERN + restore_flags(flags); +#else spin_unlock_irqrestore(&reset_lock, flags); +#endif return SCSI_RESET_SNOOZE; } @@ -2245,8 +3002,17 @@ { if (!(inb (IM_STAT_REG(host_index)) & IM_BUSY)) break; +#ifdef OLDKERN + restore_flags(flags); +#else spin_unlock_irqrestore(&reset_lock, flags); +#endif +#ifdef OLDKERN + save_flags(flags); + cli(); +#else spin_lock_irqsave(&reset_lock, flags); +#endif } /*write registers and enable system interrupts */ outl (imm_command, IM_CMD_REG(host_index)); @@ -2263,10 +3029,14 @@ printk("IBM MCA SCSI: reset did not complete within %d seconds.\n", IM_RESET_DELAY); reset_status(host_index) = IM_RESET_FINISHED_FAIL; +#ifdef OLDKERN + restore_flags(flags); +#else spin_unlock_irqrestore(&reset_lock, flags); +#endif return SCSI_RESET_ERROR; } - + if ((inb(IM_INTR_REG(host_index)) & 0x8f)==0x8f) { /* analysis done by this routine and not by the intr-routine */ if (inb(IM_INTR_REG(host_index))==0xaf) @@ -2276,18 +3046,26 @@ else /* failed, 4get it */ reset_status(host_index) = IM_RESET_NOT_IN_PROGRESS_NO_INT; outb (IM_EOI | 0xf, IM_ATTN_REG(host_index)); - } - + } + /* if reset failed, just return an error */ if (reset_status(host_index) == IM_RESET_FINISHED_FAIL) { printk("IBM MCA SCSI: reset failed.\n"); +#ifdef OLDKERN + restore_flags(flags); +#else spin_unlock_irqrestore(&reset_lock, flags); +#endif return SCSI_RESET_ERROR; } - + /* so reset finished ok - call outstanding done's, and return success */ - printk ("IBM MCA SCSI: Reset completed without known error.\n"); + printk ("IBM MCA SCSI: Reset successfully completed.\n"); +#ifdef OLDKERN + restore_flags(flags); +#else spin_unlock_irqrestore(&reset_lock, flags); +#endif for (i = 0; i < MAX_LOG_DEV; i++) { cmd_aid = ld(host_index)[i].cmd; @@ -2295,10 +3073,22 @@ { ld(host_index)[i].cmd = NULL; cmd_aid->result = DID_RESET << 16; - (cmd_aid->scsi_done) (cmd_aid); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,132) + if (flags & SCSI_RESET_SYNCHRONOUS) + { + cmd_aid->result = DID_BUS_BUSY << 16; + if (cmd_aid->scsi_done) + (cmd_aid->scsi_done) (cmd_aid); + } +#endif } } - return SCSI_RESET_SUCCESS; + if (flags & SCSI_RESET_SUGGEST_HOST_RESET) + return (SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET); + else if (flags & SCSI_RESET_SUGGEST_BUS_RESET) + return (SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET); + else + return SCSI_RESET_SUCCESS; } /*--------------------------------------------------------------------*/ @@ -2338,7 +3128,7 @@ { int a; int i; - + a = 0; for (i=0; i<=MAX_LOG_DEV; i++) a+=IBM_DS(host_index).ldn_read_access[i]+IBM_DS(host_index).ldn_write_access[i]; @@ -2349,7 +3139,7 @@ { int a; int i; - + a = 0; for (i=0; i<=MAX_LOG_DEV; i++) a+=IBM_DS(host_index).ldn_inquiry_access[i]; @@ -2360,7 +3150,7 @@ { int a; int i; - + a = 0; for (i=0; i<=MAX_LOG_DEV; i++) a+=IBM_DS(host_index).ldn_modeselect_access[i]; @@ -2375,17 +3165,24 @@ int i,id,lun,host_index; struct Scsi_Host *shpnt; unsigned long flags; - + int max_pun; + +#ifdef OLDKERN + save_flags(flags); + cli(); +#else spin_lock_irqsave(&proc_lock, flags); +#endif for (i = 0; hosts[i] && hosts[i]->host_no != hostno; i++); shpnt = hosts[i]; host_index = i; if (!shpnt) { - len += sprintf(buffer+len, "\nCan't find adapter for host number %d\n", hostno); + len += sprintf(buffer+len, "\nIBM MCA SCSI: Can't find adapter for host number %d\n", hostno); return len; } - + max_pun = subsystem_maxid(host_index); + len += sprintf(buffer+len, "\n IBM-SCSI-Subsystem-Linux-Driver, Version %s\n\n\n", IBMMCA_SCSI_DRIVER_VERSION); len += sprintf(buffer+len, " SCSI Access-Statistics:\n"); @@ -2406,8 +3203,12 @@ (bypass_controller) ? "software" : "hardware integrated"); len += sprintf(buffer+len, " Total Interrupts.........: %d\n", IBM_DS(host_index).total_interrupts); - len += sprintf(buffer+len, " Total SCSI Accesses......: %d\n", + len += sprintf(buffer+len, " Total SCSI Accesses......: %d\n", IBM_DS(host_index).total_accesses); + len += sprintf(buffer+len, " Total short SCBs.........: %d\n", + IBM_DS(host_index).scbs); + len += sprintf(buffer+len, " Total long SCBs..........: %d\n", + IBM_DS(host_index).long_scbs); len += sprintf(buffer+len, " Total SCSI READ/WRITE..: %d\n", ldn_access_total_read_write(host_index)); len += sprintf(buffer+len, " Total SCSI Inquiries...: %d\n", @@ -2428,11 +3229,11 @@ i, ldn_access_load(host_index, i), IBM_DS(host_index).ldn_read_access[i], IBM_DS(host_index).ldn_write_access[i], IBM_DS(host_index).ldn_assignments[i]); len += sprintf(buffer+len, " -----------------------------------------------------------\n\n"); - + len += sprintf(buffer+len, " Dynamical-LDN-Assignment-Statistics:\n"); len += sprintf(buffer+len, " Number of physical SCSI-devices..: %d (+ Adapter)\n", IBM_DS(host_index).total_scsi_devices); - len += sprintf(buffer+len, " Dynamical Assignment necessaray..: %s\n", + len += sprintf(buffer+len, " Dynamical Assignment necessary...: %s\n", IBM_DS(host_index).dyn_flag ? "Yes" : "No "); len += sprintf(buffer+len, " Next LDN to be assigned..........: 0x%x\n", next_ldn(host_index)); @@ -2442,47 +3243,63 @@ len += sprintf(buffer+len, "\n Current SCSI-Device-Mapping:\n"); len += sprintf(buffer+len, " Physical SCSI-Device Map Logical SCSI-Device Map\n"); len += sprintf(buffer+len, " ID\\LUN 0 1 2 3 4 5 6 7 ID\\LUN 0 1 2 3 4 5 6 7\n"); - for (id=0; id<=7; id++) + for (id=0; id length) + if (len > length) len = length; +#ifdef OLDKERN + restore_flags(flags); +#else spin_unlock_irqrestore(&proc_lock, flags); +#endif return len; } +void ibmmca_scsi_setup (char *str, int *ints) +{ + internal_ibmmca_scsi_setup (str, ints); +} + +static int option_setup(char *str) +{ + int ints[IM_MAX_HOSTS]; + char *cur = str; + int i = 1; + + while (cur && isdigit(*cur) && i <= IM_MAX_HOSTS) { + ints[i++] = simple_strtoul(cur, NULL, 0); + if ((cur = strchr(cur,',')) != NULL) cur++; + } + ints[0] = i - 1; + internal_ibmmca_scsi_setup(cur, ints); + return 0; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18) +__setup("ibmmcascsi=", option_setup); +#endif + #ifdef MODULE /* Eventually this will go into an include file, but this will be later */ Scsi_Host_Template driver_template = IBMMCA; #include "scsi_module.c" - -/* - * Module parameters - */ - -MODULE_PARM(io_port, "1-" __MODULE_STRING(IM_MAX_HOSTS) "i"); -MODULE_PARM(scsi_id, "1-" __MODULE_STRING(IM_MAX_HOSTS) "i"); -MODULE_PARM(display, "1i"); -MODULE_PARM(adisplay, "1i"); -MODULE_PARM(bypass, "1i"); -MODULE_PARM(normal, "1i"); -MODULE_PARM(ansi, "1i"); #endif /*--------------------------------------------------------------------*/ + diff -u --recursive --new-file v2.4.0-test5/linux/drivers/scsi/ibmmca.h linux/drivers/scsi/ibmmca.h --- v2.4.0-test5/linux/drivers/scsi/ibmmca.h Thu Nov 11 20:11:47 1999 +++ linux/drivers/scsi/ibmmca.h Wed Aug 9 18:59:41 2000 @@ -1,3 +1,9 @@ +/* + * Low Level Driver for the IBM Microchannel SCSI Subsystem + * (Headerfile, see README.ibmmca for description of the IBM MCA SCSI-driver + * For use under the GNU public license within the Linux-kernel project. + */ + #ifndef _IBMMCA_H #define _IBMMCA_H @@ -5,18 +11,15 @@ #include #endif -#ifndef ibmmca_header_linux_version -#define ibmmca_header_linux_version(v,p,s) (((v)<<16)+((p)<<8)+(s)) -#endif - -/* - * Low Level Driver for the IBM Microchannel SCSI Subsystem - * (Headerfile, see README.ibmmca for description of the IBM MCA SCSI-driver) - */ +/* Note to the Linux-toplevel-maintainers: + * This file contains the unified header for all available Linux-distributions. + * For reasons of maintenance, it is recommended to keep this unmodified to + * be downward compatible until I no longer get any requests from people + * using older kernel releases on their PS/2 machines. (23 Apr 2000, M.Lang) */ /* Common forward declarations for all Linux-versions: */ -/*services provided to the higher level of Linux SCSI driver */ +/* Interfaces to the midlevel Linux SCSI driver */ extern int ibmmca_proc_info (char *, char **, off_t, int, int, int); extern int ibmmca_detect (Scsi_Host_Template *); extern int ibmmca_release (struct Scsi_Host *); @@ -27,14 +30,39 @@ extern int ibmmca_biosparam (Disk *, kdev_t, int *); /*structure for /proc filesystem */ +extern struct proc_dir_entry proc_scsi_ibmmca; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,75) +/* Stuff for Linux >= 2.1.75: */ /* * 2/8/98 * Note to maintainer of IBMMCA. Do not change this initializer back to * the old format. Please ask eric@andante.jic.com if you have any questions * about this, but it will break things in the future. */ -#define IBMMCA { \ +/*initialization for Scsi_host_template type (Linux >= 2.1.75 && < 2.3.27) */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,27) +#define IBMMCA { \ + proc_dir: &proc_scsi_ibmmca, /*proc_dir*/ \ + proc_info: ibmmca_proc_info, /*proc info fn*/ \ + name: "IBM SCSI-Subsystem", /*name*/ \ + detect: ibmmca_detect, /*detect fn*/ \ + release: ibmmca_release, /*release fn*/ \ + command: ibmmca_command, /*command fn*/ \ + queuecommand: ibmmca_queuecommand, /*queuecommand fn*/ \ + abort: ibmmca_abort, /*abort fn*/ \ + reset: ibmmca_reset, /*reset fn*/ \ + bios_param: ibmmca_biosparam, /*bios fn*/ \ + can_queue: 16, /*can_queue*/ \ + this_id: 7, /*set by detect*/ \ + sg_tablesize: 16, /*sg_tablesize*/ \ + cmd_per_lun: 1, /*cmd_per_lun*/ \ + unchecked_isa_dma: 0, /*32-Bit Busmaster */ \ + use_clustering: ENABLE_CLUSTERING /*use_clustering*/ \ + } +#else +#define IBMMCA { \ proc_name: "ibmmca", /*proc_name*/ \ proc_info: ibmmca_proc_info, /*proc info fn*/ \ name: "IBM SCSI-Subsystem", /*name*/ \ @@ -52,5 +80,34 @@ unchecked_isa_dma: 0, /*32-Bit Busmaster */ \ use_clustering: ENABLE_CLUSTERING /*use_clustering*/ \ } +#endif +#else +/* Stuff for Linux < 2.1.75: */ + +/*initialization for Scsi_host_template type (Linux < 2.1.75) */ +#define IBMMCA { \ + NULL, /*next*/ \ + NULL, /*usage_count*/ \ + &proc_scsi_ibmmca, /*proc_dir*/ \ + ibmmca_proc_info, /*proc info fn*/ \ + "IBM SCSI-Subsystem", /*name*/ \ + ibmmca_detect, /*detect fn*/ \ + ibmmca_release, /*release fn*/ \ + NULL, /*info fn*/ \ + ibmmca_command, /*command fn*/ \ + ibmmca_queuecommand, /*queuecommand fn*/ \ + ibmmca_abort, /*abort fn*/ \ + ibmmca_reset, /*reset fn*/ \ + NULL, /*slave_attach fn*/ \ + ibmmca_biosparam, /*bios fn*/ \ + 16, /*can_queue*/ \ + 7, /*set by detect*/ \ + 16, /*sg_tablesize*/ \ + 1, /*cmd_per_lun*/ \ + 0, /*present*/ \ + 0, /*unchecked_isa_dma*/ \ + ENABLE_CLUSTERING /*use_clustering*/ \ + } +#endif /* kernelversion selection */ #endif /* _IBMMCA_H */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/scsi/ips.c linux/drivers/scsi/ips.c --- v2.4.0-test5/linux/drivers/scsi/ips.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/scsi/ips.c Fri Aug 4 17:58:10 2000 @@ -66,6 +66,18 @@ /* 3.60.01 - Remove bogus error check in passthru routine */ /* 3.60.02 - Make DCDB direction based on lookup table */ /* - Only allow one DCDB command to a SCSI ID at a time */ +/* 4.00.00 - Add support for ServeRAID 4 */ +/* 4.00.01 - Add support for First Failure Data Capture */ +/* 4.00.02 - Fix problem with PT DCDB with no buffer */ +/* 4.00.03 - Add alternative passthru interface */ +/* - Add ability to flash ServeRAID BIOS */ +/* 4.00.04 - Rename structures/constants to be prefixed with IPS_ */ +/* 4.00.05 - Remove wish_block from init routine */ +/* - Use linux/spinlock.h instead of asm/spinlock.h for kernels */ +/* 2.3.18 and later */ +/* - Sync with other changes from the 2.3 kernels */ +/* 4.00.06 - Fix timeout with initial FFDC command */ +/* 4.00.06a - Port to 2.4 (trivial) -- Christoph Hellwig */ /* */ /*****************************************************************************/ @@ -78,9 +90,7 @@ * */ -#if defined (MODULE) - #include -#endif /* MODULE */ +#include #include #include @@ -110,14 +120,33 @@ #include #include + +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,18) #include +#else +#include +#endif + #include /* * DRIVER_VER */ -#define IPS_VERSION_HIGH "3.60" /* MUST be 4 chars */ -#define IPS_VERSION_LOW ".02 " /* MUST be 4 chars */ +#define IPS_VERSION_HIGH "4.00" /* MUST be 4 chars */ +#define IPS_VERSION_LOW ".06 " /* MUST be 4 chars */ + +#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27) +struct proc_dir_entry proc_scsi_ips = { +#if !defined(PROC_SCSI_IPS) + 0, /* Use dynamic inode allocation */ +#else + PROC_SCSI_IPS, +#endif + 3, "ips", + S_IFDIR | S_IRUGO | S_IXUGO, 2 +} +; +#endif #if !defined(__i386__) #error "This driver has only been tested on the x86 platform" @@ -132,7 +161,7 @@ #endif #if IPS_DEBUG >= 12 - #define DBG(s) printk(KERN_NOTICE s "\n"); MDELAY(2*ONE_SEC) + #define DBG(s) printk(KERN_NOTICE s "\n"); MDELAY(2*IPS_ONE_SEC) #elif IPS_DEBUG >= 11 #define DBG(s) printk(KERN_NOTICE s "\n") #else @@ -149,7 +178,7 @@ static int ips_cmd_timeout = 60; static int ips_reset_timeout = 60 * 5; -#define MAX_ADAPTER_NAME 6 +#define MAX_ADAPTER_NAME 7 static char ips_adapter_name[][30] = { "ServeRAID", @@ -157,64 +186,65 @@ "ServeRAID on motherboard", "ServeRAID on motherboard", "ServeRAID 3H", - "ServeRAID 3L" + "ServeRAID 3L", + "ServeRAID 4H" }; /* * Direction table */ static char ips_command_direction[] = { -IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, -IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK, -IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, -IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_OUT, -IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_OUT, -IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_IN, -IPS_DATA_UNK, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_UNK, -IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, -IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_NONE, -IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, -IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT, -IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_NONE, -IPS_DATA_UNK, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_UNK, -IPS_DATA_NONE, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_NONE, -IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_OUT, -IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_NONE, -IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_IN, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_OUT, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, -IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK +IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, +IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK, +IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, +IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_OUT, +IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_OUT, +IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_IN, +IPS_DATA_UNK, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_UNK, +IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, +IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_NONE, +IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, +IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT, +IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_NONE, +IPS_DATA_UNK, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_UNK, +IPS_DATA_NONE, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_NONE, +IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_OUT, +IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_NONE, +IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_IN, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_OUT, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, +IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK }; /* @@ -232,8 +262,8 @@ void do_ipsintr(int, void *, struct pt_regs *); static int ips_hainit(ips_ha_t *); static int ips_map_status(ips_scb_t *, ips_stat_t *); -static int ips_send(ips_ha_t *, ips_scb_t *, scb_callback); -static int ips_send_wait(ips_ha_t *, ips_scb_t *, int); +static int ips_send(ips_ha_t *, ips_scb_t *, ips_scb_callback); +static int ips_send_wait(ips_ha_t *, ips_scb_t *, int, int); static int ips_send_cmd(ips_ha_t *, ips_scb_t *); static int ips_chkstatus(ips_ha_t *); static int ips_online(ips_ha_t *, ips_scb_t *); @@ -247,14 +277,14 @@ static int ips_issue(ips_ha_t *, ips_scb_t *); static int ips_isintr(ips_ha_t *); static int ips_wait(ips_ha_t *, int, int); -static int ips_write_driver_status(ips_ha_t *); -static int ips_read_adapter_status(ips_ha_t *); -static int ips_read_subsystem_parameters(ips_ha_t *); -static int ips_read_config(ips_ha_t *); -static int ips_clear_adapter(ips_ha_t *); -static int ips_readwrite_page5(ips_ha_t *, int); +static int ips_write_driver_status(ips_ha_t *, int); +static int ips_read_adapter_status(ips_ha_t *, int); +static int ips_read_subsystem_parameters(ips_ha_t *, int); +static int ips_read_config(ips_ha_t *, int); +static int ips_clear_adapter(ips_ha_t *, int); +static int ips_readwrite_page5(ips_ha_t *, int, int); static void ips_intr(ips_ha_t *); -static void ips_next(ips_ha_t *); +static void ips_next(ips_ha_t *, int); static void ipsintr_blocking(ips_ha_t *, struct ips_scb *); static void ipsintr_done(ips_ha_t *, struct ips_scb *); static void ips_done(ips_ha_t *, ips_scb_t *); @@ -262,6 +292,9 @@ static void ips_init_scb(ips_ha_t *, ips_scb_t *); static void ips_freescb(ips_ha_t *, ips_scb_t *); static void ips_statinit(ips_ha_t *); +static void ips_fix_ffdc_time(ips_ha_t *, ips_scb_t *, time_t); +static void ips_ffdc_reset(ips_ha_t *, int); +static void ips_ffdc_time(ips_ha_t *, int); static ips_scb_t * ips_getscb(ips_ha_t *); static inline void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *); static inline void ips_putq_scb_tail(ips_scb_queue_t *, ips_scb_t *); @@ -271,17 +304,26 @@ static inline void ips_putq_wait_tail(ips_wait_queue_t *, Scsi_Cmnd *); static inline Scsi_Cmnd * ips_removeq_wait_head(ips_wait_queue_t *); static inline Scsi_Cmnd * ips_removeq_wait(ips_wait_queue_t *, Scsi_Cmnd *); +static inline void ips_putq_copp_head(ips_copp_queue_t *, ips_copp_wait_item_t *); +static inline void ips_putq_copp_tail(ips_copp_queue_t *, ips_copp_wait_item_t *); +static inline ips_copp_wait_item_t * ips_removeq_copp(ips_copp_queue_t *, ips_copp_wait_item_t *); +static inline ips_copp_wait_item_t * ips_removeq_copp_head(ips_copp_queue_t *); +static int ips_erase_bios(ips_ha_t *); +static int ips_program_bios(ips_ha_t *, char *, int); +static int ips_verify_bios(ips_ha_t *, char *, int); #ifndef NO_IPS_CMDLINE static int ips_is_passthru(Scsi_Cmnd *); static int ips_make_passthru(ips_ha_t *, Scsi_Cmnd *, ips_scb_t *); static int ips_usrcmd(ips_ha_t *, ips_passthru_t *, ips_scb_t *); +static int ips_newusrcmd(ips_ha_t *, ips_passthru_t *, ips_scb_t *); +static void ips_cleanup_passthru(ips_ha_t *, ips_scb_t *); #endif int ips_proc_info(char *, char **, off_t, int, int, int); static int ips_host_info(ips_ha_t *, char *, off_t, int); -static void copy_mem_info(INFOSTR *, char *, int); -static int copy_info(INFOSTR *, char *, ...); +static void copy_mem_info(IPS_INFOSTR *, char *, int); +static int copy_info(IPS_INFOSTR *, char *, ...); /*--------------------------------------------------------------------------*/ /* Exported Functions */ @@ -295,6 +337,8 @@ /* */ /* Detect and initialize the driver */ /* */ +/* NOTE: this routine is called under the io_request_lock spinlock */ +/* */ /****************************************************************************/ int ips_detect(Scsi_Host_Template *SHT) { @@ -302,6 +346,7 @@ ips_ha_t *ha; u32 io_addr; u16 planer; + u8 revision_id; u8 bus; u8 func; u8 irq; @@ -311,7 +356,11 @@ DBG("ips_detect"); SHT->proc_info = ips_proc_info; +#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27) + SHT->proc_dir = &proc_scsi_ips; +#else SHT->proc_name = "ips"; +#endif #if defined(CONFIG_PCI) @@ -325,26 +374,27 @@ if (!(dev = pci_find_device(IPS_VENDORID, IPS_DEVICEID, dev))) break; + if (pci_enable_device(dev)) - break; + break; + /* stuff that we get in dev */ irq = dev->irq; bus = dev->bus->number; func = dev->devfn; io_addr = pci_resource_start(dev, 0); + + /* check I/O address */ + if (pci_resource_flags(dev, 0) & IORESOURCE_MEM) + continue; /* get planer status */ if (pci_read_config_word(dev, 0x04, &planer)) { printk(KERN_WARNING "(%s%d) can't get planer status.\n", ips_name, index); - continue; } - /* check I/O address */ - if (pci_resource_flags(dev, 0) & IORESOURCE_MEM) - continue; - /* check to see if an onboard planer controller is disabled */ if (!(planer & 0x000C)) { @@ -361,6 +411,14 @@ ips_name, index, bus, func, irq, io_addr); #endif + /* get the revision ID */ + if (pci_read_config_byte(dev, 0x08, &revision_id)) { + printk(KERN_WARNING "(%s%d) can't get revision id.\n", + ips_name, index); + + continue; + } + /* found a controller */ sh = scsi_register(SHT, sizeof(ips_ha_t)); @@ -371,19 +429,23 @@ continue; } - ha = HA(sh); + ha = IPS_HA(sh); memset(ha, 0, sizeof(ips_ha_t)); /* Initialize spin lock */ spin_lock_init(&ha->scb_lock); spin_lock_init(&ha->copp_lock); + spin_lock_init(&ha->ips_lock); + spin_lock_init(&ha->copp_waitlist.lock); + spin_lock_init(&ha->scb_waitlist.lock); + spin_lock_init(&ha->scb_activelist.lock); ips_sh[ips_num_controllers] = sh; ips_ha[ips_num_controllers] = ha; ips_num_controllers++; ha->active = 1; - ha->enq = kmalloc(sizeof(ENQCMD), GFP_KERNEL|GFP_DMA); + ha->enq = kmalloc(sizeof(IPS_ENQ), GFP_KERNEL|GFP_DMA); if (!ha->enq) { printk(KERN_WARNING "(%s%d) Unable to allocate host inquiry structure - skipping contoller\n", @@ -394,7 +456,7 @@ continue; } - ha->adapt = kmalloc(sizeof(ADAPTER_AREA), GFP_KERNEL|GFP_DMA); + ha->adapt = kmalloc(sizeof(IPS_ADAPTER), GFP_KERNEL|GFP_DMA); if (!ha->adapt) { printk(KERN_WARNING "(%s%d) Unable to allocate host adapt structure - skipping controller\n", @@ -405,7 +467,7 @@ continue; } - ha->conf = kmalloc(sizeof(CONFCMD), GFP_KERNEL|GFP_DMA); + ha->conf = kmalloc(sizeof(IPS_CONF), GFP_KERNEL|GFP_DMA); if (!ha->conf) { printk(KERN_WARNING "(%s%d) Unable to allocate host conf structure - skipping controller\n", @@ -416,7 +478,7 @@ continue; } - ha->nvram = kmalloc(sizeof(NVRAM_PAGE5), GFP_KERNEL|GFP_DMA); + ha->nvram = kmalloc(sizeof(IPS_NVRAM_P5), GFP_KERNEL|GFP_DMA); if (!ha->nvram) { printk(KERN_WARNING "(%s%d) Unable to allocate host nvram structure - skipping controller\n", @@ -427,7 +489,7 @@ continue; } - ha->subsys = kmalloc(sizeof(SUBSYS_PARAM), GFP_KERNEL|GFP_DMA); + ha->subsys = kmalloc(sizeof(IPS_SUBSYS), GFP_KERNEL|GFP_DMA); if (!ha->subsys) { printk(KERN_WARNING "(%s%d) Unable to allocate host subsystem structure - skipping controller\n", @@ -438,7 +500,7 @@ continue; } - ha->dummy = kmalloc(sizeof(BASIC_IO_CMD), GFP_KERNEL|GFP_DMA); + ha->dummy = kmalloc(sizeof(IPS_IO_CMD), GFP_KERNEL|GFP_DMA); if (!ha->dummy) { printk(KERN_WARNING "(%s%d) Unable to allocate host dummy structure - skipping controller\n", @@ -449,6 +511,17 @@ continue; } + ha->ioctl_data = kmalloc(IPS_IOCTL_SIZE, GFP_KERNEL|GFP_DMA); + ha->ioctl_datasize = IPS_IOCTL_SIZE; + if (!ha->ioctl_data) { + printk(KERN_WARNING "(%s%d) Unable to allocate ioctl data - skipping controller\n", + ips_name, index); + + ha->active = 0; + + continue; + } + /* Store away needed values for later use */ sh->io_port = io_addr; sh->n_io_port = 255; @@ -465,6 +538,7 @@ ha->io_addr = io_addr; ha->irq = irq; ha->host_num = index; + ha->revision_id = revision_id; /* install the interrupt handler */ if (request_irq(irq, do_ipsintr, SA_SHIRQ, ips_name, ha)) { @@ -491,7 +565,7 @@ } memset(ha->scbs, 0, sizeof(ips_scb_t)); - ha->scbs->sg_list = (SG_LIST *) kmalloc(sizeof(SG_LIST) * MAX_SG_ELEMENTS, GFP_KERNEL|GFP_DMA); + ha->scbs->sg_list = (IPS_SG_LIST *) kmalloc(sizeof(IPS_SG_LIST) * IPS_MAX_SG, GFP_KERNEL|GFP_DMA); if (!ha->scbs->sg_list) { /* couldn't allocate a temp SCB S/G list */ printk(KERN_WARNING "(%s%d) unable to allocate CCBs - skipping contoller\n", @@ -569,7 +643,7 @@ panic("(%s) release, invalid Scsi_Host pointer.\n", ips_name); - ha = HA(sh); + ha = IPS_HA(sh); if (!ha) return (FALSE); @@ -580,11 +654,11 @@ ips_init_scb(ha, scb); scb->timeout = ips_cmd_timeout; - scb->cdb[0] = FLUSH_CACHE; + scb->cdb[0] = IPS_CMD_FLUSH; - scb->cmd.flush_cache.op_code = FLUSH_CACHE; + scb->cmd.flush_cache.op_code = IPS_CMD_FLUSH; scb->cmd.flush_cache.command_id = IPS_COMMAND_ID(ha, scb); - scb->cmd.flush_cache.state = NORM_STATE; + scb->cmd.flush_cache.state = IPS_NORM_STATE; scb->cmd.flush_cache.reserved = 0; scb->cmd.flush_cache.reserved2 = 0; scb->cmd.flush_cache.reserved3 = 0; @@ -593,7 +667,7 @@ printk("(%s%d) Flushing Cache.\n", ips_name, ha->host_num); /* send command */ - if (ips_send_wait(ha, scb, ips_cmd_timeout) == IPS_FAILURE) + if (ips_send_wait(ha, scb, ips_cmd_timeout, IPS_INTR_ON) == IPS_FAILURE) printk("(%s%d) Incomplete Flush.\n", ips_name, ha->host_num); printk("(%s%d) Flushing Complete.\n", ips_name, ha->host_num); @@ -625,6 +699,7 @@ int ips_eh_abort(Scsi_Cmnd *SC) { ips_ha_t *ha; + ips_copp_wait_item_t *item; DBG("ips_eh_abort"); @@ -651,9 +726,23 @@ if (test_and_set_bit(IPS_IN_ABORT, &ha->flags)) return (FAILED); + /* See if the command is on the copp queue */ + IPS_QUEUE_LOCK(&ha->copp_waitlist); + item = ha->copp_waitlist.head; + while ((item) && (item->scsi_cmd != SC)) + item = item->next; + IPS_QUEUE_UNLOCK(&ha->copp_waitlist); + + if (item) { + /* Found it */ + ips_removeq_copp(&ha->copp_waitlist, item); + clear_bit(IPS_IN_ABORT, &ha->flags); + + return (SUCCESS); + } + /* See if the command is on the wait queue */ - if (ips_removeq_wait(&ha->scb_waitlist, SC) || - ips_removeq_wait(&ha->copp_waitlist, SC)) { + if (ips_removeq_wait(&ha->scb_waitlist, SC)) { /* command not sent yet */ clear_bit(IPS_IN_ABORT, &ha->flags); @@ -678,6 +767,7 @@ int ips_abort(Scsi_Cmnd *SC) { ips_ha_t *ha; + ips_copp_wait_item_t *item; DBG("ips_abort"); @@ -704,9 +794,23 @@ if (test_and_set_bit(IPS_IN_ABORT, &ha->flags)) return (SCSI_ABORT_SNOOZE); + /* See if the command is on the copp queue */ + IPS_QUEUE_LOCK(&ha->copp_waitlist); + item = ha->copp_waitlist.head; + while ((item) && (item->scsi_cmd != SC)) + item = item->next; + IPS_QUEUE_UNLOCK(&ha->copp_waitlist); + + if (item) { + /* Found it */ + ips_removeq_copp(&ha->copp_waitlist, item); + clear_bit(IPS_IN_ABORT, &ha->flags); + + return (SCSI_ABORT_PENDING); + } + /* See if the command is on the wait queue */ - if (ips_removeq_wait(&ha->scb_waitlist, SC) || - ips_removeq_wait(&ha->copp_waitlist, SC)) { + if (ips_removeq_wait(&ha->scb_waitlist, SC)) { /* command not sent yet */ clear_bit(IPS_IN_ABORT, &ha->flags); @@ -727,11 +831,15 @@ /* */ /* Reset the controller (with new eh error code) */ /* */ +/* NOTE: this routine is called under the io_request_lock spinlock */ +/* */ /****************************************************************************/ int ips_eh_reset(Scsi_Cmnd *SC) { - ips_ha_t *ha; - ips_scb_t *scb; + u32 cpu_flags; + ips_ha_t *ha; + ips_scb_t *scb; + ips_copp_wait_item_t *item; DBG("ips_eh_reset"); @@ -765,11 +873,25 @@ if (test_and_set_bit(IPS_IN_RESET, &ha->flags)) return (FAILED); - /* See if the command is on the waiting queue */ - if (ips_removeq_wait(&ha->scb_waitlist, SC) || - ips_removeq_wait(&ha->copp_waitlist, SC)) { + /* See if the command is on the copp queue */ + IPS_QUEUE_LOCK(&ha->copp_waitlist); + item = ha->copp_waitlist.head; + while ((item) && (item->scsi_cmd != SC)) + item = item->next; + IPS_QUEUE_UNLOCK(&ha->copp_waitlist); + + if (item) { + /* Found it */ + ips_removeq_copp(&ha->copp_waitlist, item); + clear_bit(IPS_IN_RESET, &ha->flags); + + return (SUCCESS); + } + + /* See if the command is on the wait queue */ + if (ips_removeq_wait(&ha->scb_waitlist, SC)) { /* command not sent yet */ - clear_bit(IPS_IN_ABORT, &ha->flags); + clear_bit(IPS_IN_RESET, &ha->flags); return (SUCCESS); } @@ -784,25 +906,39 @@ return (FAILED); } - if (!ips_clear_adapter(ha)) { + if (!ips_clear_adapter(ha, IPS_INTR_IORL)) { clear_bit(IPS_IN_RESET, &ha->flags); return (FAILED); } + /* FFDC */ + if (ha->subsys->param[3] & 0x300000) { + struct timeval tv; + + do_gettimeofday(&tv); + IPS_HA_LOCK(cpu_flags); + ha->last_ffdc = tv.tv_sec; + ha->reset_count++; + IPS_HA_UNLOCK(cpu_flags); + ips_ffdc_reset(ha, IPS_INTR_IORL); + } + /* Now fail all of the active commands */ #if IPS_DEBUG >= 1 printk(KERN_WARNING "(%s%d) Failing active commands\n", ips_name, ha->host_num); #endif while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) { - scb->scsi_cmd->result = DID_RESET << 16; + scb->scsi_cmd->result = (DID_RESET << 16) | (SUGGEST_RETRY << 24); scb->scsi_cmd->scsi_done(scb->scsi_cmd); ips_freescb(ha, scb); } /* Reset the number of active IOCTLs */ + IPS_HA_LOCK(cpu_flags); ha->num_ioctl = 0; + IPS_HA_UNLOCK(cpu_flags); clear_bit(IPS_IN_RESET, &ha->flags); @@ -814,7 +950,7 @@ * handler wants to do this and since * interrupts are turned off here.... */ - ips_next(ha); + ips_next(ha, IPS_INTR_IORL); } return (SUCCESS); @@ -831,11 +967,15 @@ /* */ /* Reset the controller */ /* */ +/* NOTE: this routine is called under the io_request_lock spinlock */ +/* */ /****************************************************************************/ int ips_reset(Scsi_Cmnd *SC, unsigned int flags) { - ips_ha_t *ha; - ips_scb_t *scb; + u32 cpu_flags; + ips_ha_t *ha; + ips_scb_t *scb; + ips_copp_wait_item_t *item; DBG("ips_reset"); @@ -869,11 +1009,25 @@ if (test_and_set_bit(IPS_IN_RESET, &ha->flags)) return (SCSI_RESET_SNOOZE); - /* See if the command is on the waiting queue */ - if (ips_removeq_wait(&ha->scb_waitlist, SC) || - ips_removeq_wait(&ha->copp_waitlist, SC)) { + /* See if the command is on the copp queue */ + IPS_QUEUE_LOCK(&ha->copp_waitlist); + item = ha->copp_waitlist.head; + while ((item) && (item->scsi_cmd != SC)) + item = item->next; + IPS_QUEUE_UNLOCK(&ha->copp_waitlist); + + if (item) { + /* Found it */ + ips_removeq_copp(&ha->copp_waitlist, item); + clear_bit(IPS_IN_RESET, &ha->flags); + + return (SCSI_RESET_SNOOZE); + } + + /* See if the command is on the wait queue */ + if (ips_removeq_wait(&ha->scb_waitlist, SC)) { /* command not sent yet */ - clear_bit(IPS_IN_ABORT, &ha->flags); + clear_bit(IPS_IN_RESET, &ha->flags); return (SCSI_RESET_SNOOZE); } @@ -885,25 +1039,39 @@ return (SCSI_RESET_ERROR); } - if (!ips_clear_adapter(ha)) { + if (!ips_clear_adapter(ha, IPS_INTR_IORL)) { clear_bit(IPS_IN_RESET, &ha->flags); return (SCSI_RESET_ERROR); } + /* FFDC */ + if (ha->subsys->param[3] & 0x300000) { + struct timeval tv; + + do_gettimeofday(&tv); + IPS_HA_LOCK(cpu_flags); + ha->last_ffdc = tv.tv_sec; + ha->reset_count++; + IPS_HA_UNLOCK(cpu_flags); + ips_ffdc_reset(ha, IPS_INTR_IORL); + } + /* Now fail all of the active commands */ #if IPS_DEBUG >= 1 printk(KERN_WARNING "(%s%d) Failing active commands\n", ips_name, ha->host_num); #endif while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) { - scb->scsi_cmd->result = DID_RESET << 16; + scb->scsi_cmd->result = (DID_RESET << 16) | (SUGGEST_RETRY << 24); scb->scsi_cmd->scsi_done(scb->scsi_cmd); ips_freescb(ha, scb); } /* Reset the number of active IOCTLs */ + IPS_HA_LOCK(cpu_flags); ha->num_ioctl = 0; + IPS_HA_UNLOCK(cpu_flags); clear_bit(IPS_IN_RESET, &ha->flags); @@ -915,7 +1083,7 @@ * handler wants to do this and since * interrupts are turned off here.... */ - ips_next(ha); + ips_next(ha, IPS_INTR_IORL); } return (SCSI_RESET_SUCCESS); @@ -932,10 +1100,15 @@ /* */ /* Send a command to the controller */ /* */ +/* NOTE: */ +/* Linux obtains io_request_lock before calling this function */ +/* */ /****************************************************************************/ int ips_queue(Scsi_Cmnd *SC, void (*done) (Scsi_Cmnd *)) { ips_ha_t *ha; + u32 cpu_flags; + DECLARE_MUTEX_LOCKED(sem); DBG("ips_queue"); @@ -949,19 +1122,27 @@ #ifndef NO_IPS_CMDLINE if (ips_is_passthru(SC)) { + IPS_QUEUE_LOCK(&ha->copp_waitlist); if (ha->copp_waitlist.count == IPS_MAX_IOCTL_QUEUE) { + IPS_QUEUE_UNLOCK(&ha->copp_waitlist); SC->result = DID_BUS_BUSY << 16; done(SC); return (0); + } else { + IPS_QUEUE_UNLOCK(&ha->copp_waitlist); } } else { #endif + IPS_QUEUE_LOCK(&ha->scb_waitlist); if (ha->scb_waitlist.count == IPS_MAX_QUEUE) { + IPS_QUEUE_UNLOCK(&ha->scb_waitlist); SC->result = DID_BUS_BUSY << 16; done(SC); return (0); + } else { + IPS_QUEUE_UNLOCK(&ha->scb_waitlist); } #ifndef NO_IPS_CMDLINE @@ -978,21 +1159,82 @@ SC->target, SC->lun); #if IPS_DEBUG >= 11 - MDELAY(2*ONE_SEC); + MDELAY(2*IPS_ONE_SEC); #endif #endif #ifndef NO_IPS_CMDLINE - if (ips_is_passthru(SC)) - ips_putq_wait_tail(&ha->copp_waitlist, SC); + if (ips_is_passthru(SC)) { + ips_copp_wait_item_t *scratch; + + /* allocate space for the scribble */ + scratch = kmalloc(sizeof(ips_copp_wait_item_t), GFP_KERNEL); + + if (!scratch) { + SC->result = DID_ERROR << 16; + done(SC); + + return (0); + } + + scratch->scsi_cmd = SC; + scratch->sem = &sem; + scratch->next = NULL; + + ips_putq_copp_tail(&ha->copp_waitlist, scratch); + } else #endif ips_putq_wait_tail(&ha->scb_waitlist, SC); + IPS_HA_LOCK(cpu_flags); if ((!test_bit(IPS_IN_INTR, &ha->flags)) && (!test_bit(IPS_IN_ABORT, &ha->flags)) && - (!test_bit(IPS_IN_RESET, &ha->flags))) - ips_next(ha); + (!test_bit(IPS_IN_RESET, &ha->flags))) { + IPS_HA_UNLOCK(cpu_flags); + ips_next(ha, IPS_INTR_IORL); + } else { + IPS_HA_UNLOCK(cpu_flags); + } + + /* + * If this request was a new style IOCTL wait + * for it to finish. + * + * NOTE: we relinquished the lock above so this should + * not cause contention problems + */ + if (ips_is_passthru(SC) && SC->cmnd[0] == IPS_IOCTL_NEW_COMMAND) { + char *user_area; + char *kern_area; + u32 datasize; + + /* free io_request_lock */ + spin_unlock_irq(&io_request_lock); + + /* wait for the command to finish */ + down(&sem); + + /* reobtain the lock */ + spin_lock_irq(&io_request_lock); + + /* command finished -- copy back */ + user_area = *((char **) &SC->cmnd[4]); + kern_area = ha->ioctl_data; + datasize = *((u32 *) &SC->cmnd[8]); + + if (copy_to_user(user_area, kern_area, datasize) > 0) { +#if IPS_DEBUG_PT >= 1 + printk(KERN_NOTICE "(%s%d) passthru failed - unable to copy out user data\n", + ips_name, ha->host_num); +#endif + + SC->result = DID_ERROR << 16; + SC->scsi_done(SC); + } else { + SC->scsi_done(SC); + } + } return (0); } @@ -1024,17 +1266,17 @@ if (!ha->active) return (0); - if (!ips_read_adapter_status(ha)) + if (!ips_read_adapter_status(ha, IPS_INTR_ON)) /* ?!?! Enquiry command failed */ return (0); if ((disk->capacity > 0x400000) && ((ha->enq->ucMiscFlag & 0x8) == 0)) { - heads = NORM_MODE_HEADS; - sectors = NORM_MODE_SECTORS; + heads = IPS_NORM_HEADS; + sectors = IPS_NORM_SECTORS; } else { - heads = COMP_MODE_HEADS; - sectors = COMP_MODE_SECTORS; + heads = IPS_COMP_HEADS; + sectors = IPS_COMP_SECTORS; } cylinders = disk->capacity / (heads * sectors); @@ -1063,7 +1305,7 @@ void do_ipsintr(int irq, void *dev_id, struct pt_regs *regs) { ips_ha_t *ha; - unsigned int cpu_flags; + u32 cpu_flags; DBG("do_ipsintr"); @@ -1096,6 +1338,9 @@ clear_bit(IPS_IN_INTR, &ha->flags); spin_unlock_irqrestore(&io_request_lock, cpu_flags); + + /* start the next command */ + ips_next(ha, IPS_INTR_ON); } /****************************************************************************/ @@ -1114,6 +1359,7 @@ ips_stat_t *sp; ips_scb_t *scb; int status; + u32 cpu_flags; DBG("ips_intr"); @@ -1123,6 +1369,7 @@ if (!ha->active) return; + IPS_HA_LOCK(cpu_flags); while (ips_isintr(ha)) { sp = &ha->sp; @@ -1139,10 +1386,12 @@ * use the callback function to finish things up * NOTE: interrupts are OFF for this */ + IPS_HA_UNLOCK(cpu_flags); (*scb->callback) (ha, scb); + IPS_HA_LOCK(cpu_flags); } - clear_bit(IPS_IN_INTR, &ha->flags); + IPS_HA_UNLOCK(cpu_flags); } /****************************************************************************/ @@ -1162,7 +1411,7 @@ DBG("ips_info"); - ha = HA(SH); + ha = IPS_HA(SH); if (!ha) return (NULL); @@ -1250,10 +1499,10 @@ if (!SC) return (0); - if ((SC->channel == 0) && + if (((SC->cmnd[0] == IPS_IOCTL_COMMAND) || (SC->cmnd[0] == IPS_IOCTL_NEW_COMMAND)) && + (SC->channel == 0) && (SC->target == IPS_ADAPTER_ID) && (SC->lun == 0) && - (SC->cmnd[0] == 0x0d) && (SC->request_bufflen) && (!SC->use_sg) && (((char *) SC->request_buffer)[0] == 'C') && @@ -1268,7 +1517,7 @@ /****************************************************************************/ /* */ -/* Routine Name: ips_is_passthru */ +/* Routine Name: ips_make_passthru */ /* */ /* Routine Description: */ /* */ @@ -1315,17 +1564,23 @@ } pt = (ips_passthru_t *) SC->request_buffer; - scb->scsi_cmd = SC; - - if (SC->request_bufflen < (sizeof(ips_passthru_t) + pt->CmdBSize)) { - /* wrong size */ -#if IPS_DEBUG_PT >= 1 - printk(KERN_NOTICE "(%s%d) Passthru structure wrong size\n", - ips_name, ha->host_num); -#endif - return (IPS_FAILURE); - } + /* + * Some notes about the passthru interface used + * + * IF the scsi op_code == 0x0d then we assume + * that the data came along with/goes with the + * packet we received from the sg driver. In this + * case the CmdBSize field of the pt structure is + * used for the size of the buffer. + * + * IF the scsi op_code == 0x81 then we assume that + * we will need our own buffer and we will copy the + * data to/from the user buffer passed in the scsi + * command. The data address resides at offset 4 + * in the scsi command. The length of the data resides + * at offset 8 in the scsi command. + */ switch (pt->CoppCmd) { case IPS_NUMCTRLS: @@ -1334,19 +1589,128 @@ SC->result = DID_OK << 16; return (IPS_SUCCESS_IMM); + case IPS_CTRLINFO: memcpy(SC->request_buffer + sizeof(ips_passthru_t), ha, sizeof(ips_ha_t)); SC->result = DID_OK << 16; return (IPS_SUCCESS_IMM); - case COPPUSRCMD: - if (ips_usrcmd(ha, pt, scb)) - return (IPS_SUCCESS); - else - return (IPS_FAILURE); + + case IPS_COPPUSRCMD: + case IPS_COPPIOCCMD: + if (SC->cmnd[0] == IPS_IOCTL_COMMAND) { + if (SC->request_bufflen < (sizeof(ips_passthru_t) + pt->CmdBSize)) { + /* wrong size */ + #if IPS_DEBUG_PT >= 1 + printk(KERN_NOTICE "(%s%d) Passthru structure wrong size\n", + ips_name, ha->host_num); + #endif + + return (IPS_FAILURE); + } + + if (ips_usrcmd(ha, pt, scb)) + return (IPS_SUCCESS); + else + return (IPS_FAILURE); + } else if (SC->cmnd[0] == IPS_IOCTL_NEW_COMMAND) { + if (SC->request_bufflen < (sizeof(ips_passthru_t))) { + /* wrong size */ + #if IPS_DEBUG_PT >= 1 + printk(KERN_NOTICE "(%s%d) Passthru structure wrong size\n", + ips_name, ha->host_num); + #endif + + return (IPS_FAILURE); + } + + if (ips_newusrcmd(ha, pt, scb)) + return (IPS_SUCCESS); + else + return (IPS_FAILURE); + } + break; - } + + case IPS_FLASHBIOS: + /* we must use the new interface */ + if (SC->cmnd[0] != IPS_IOCTL_NEW_COMMAND) + return (IPS_FAILURE); + + /* don't flash the BIOS on future cards */ + if (ha->revision_id > IPS_REVID_TROMBONE64) { +#if IPS_DEBUG_PT >= 1 + printk(KERN_NOTICE "(%s%d) flash bios failed - unsupported controller\n", + ips_name, ha->host_num); +#endif + return (IPS_FAILURE); + } + + /* copy in the size/buffer ptr from the scsi command */ + memcpy(&pt->CmdBuffer, &SC->cmnd[4], 4); + memcpy(&pt->CmdBSize, &SC->cmnd[8], 4); + + /* must have a buffer */ + if ((!pt->CmdBSize) || (!pt->CmdBuffer)) + return (IPS_FAILURE); + + /* make sure buffer is big enough */ + if (pt->CmdBSize > ha->ioctl_datasize) { + void *bigger_struct; + + /* try to allocate a bigger struct */ + bigger_struct = kmalloc(pt->CmdBSize, GFP_KERNEL|GFP_DMA); + if (bigger_struct) { + /* free the old memory */ + kfree(ha->ioctl_data); + + /* use the new memory */ + ha->ioctl_data = bigger_struct; + ha->ioctl_datasize = pt->CmdBSize; + } else + return (IPS_FAILURE); + } + + /* copy in the buffer */ + if (copy_from_user(ha->ioctl_data, pt->CmdBuffer, pt->CmdBSize) > 0) { +#if IPS_DEBUG_PT >= 1 + printk(KERN_NOTICE "(%s%d) flash bios failed - unable to copy user buffer\n", + ips_name, ha->host_num); +#endif + + return (IPS_FAILURE); + } + + if (ips_erase_bios(ha)) { +#if IPS_DEBUG_PT >= 1 + printk(KERN_NOTICE "(%s%d) flash bios failed - unable to erase flash\n", + ips_name, ha->host_num); +#endif + + return (IPS_FAILURE); + } + + if (ips_program_bios(ha, ha->ioctl_data, pt->CmdBSize)) { +#if IPS_DEBUG_PT >= 1 + printk(KERN_NOTICE "(%s%d) flash bios failed - unable to program flash\n", + ips_name, ha->host_num); +#endif + + return (IPS_FAILURE); + } + + if (ips_verify_bios(ha, ha->ioctl_data, pt->CmdBSize)) { +#if IPS_DEBUG_PT >= 1 + printk(KERN_NOTICE "(%s%d) flash bios failed - unable to verify flash\n", + ips_name, ha->host_num); +#endif + + return (IPS_FAILURE); + } + + return (IPS_SUCCESS_IMM); + } /* end switch */ return (IPS_FAILURE); } @@ -1362,7 +1726,7 @@ /****************************************************************************/ static int ips_usrcmd(ips_ha_t *ha, ips_passthru_t *pt, ips_scb_t *scb) { - SG_LIST *sg_list; + IPS_SG_LIST *sg_list; DBG("ips_usrcmd"); @@ -1373,15 +1737,15 @@ sg_list = scb->sg_list; /* copy in the CP */ - memcpy(&scb->cmd, &pt->CoppCP.cmd, sizeof(IOCTL_INFO)); - memcpy(&scb->dcdb, &pt->CoppCP.dcdb, sizeof(DCDB_TABLE)); + memcpy(&scb->cmd, &pt->CoppCP.cmd, sizeof(IPS_IOCTL_CMD)); + memcpy(&scb->dcdb, &pt->CoppCP.dcdb, sizeof(IPS_DCDB_TABLE)); /* FIX stuff that might be wrong */ scb->sg_list = sg_list; scb->scb_busaddr = VIRT_TO_BUS(scb); - scb->bus = 0; - scb->target_id = 0; - scb->lun = 0; + scb->bus = scb->scsi_cmd->channel; + scb->target_id = scb->scsi_cmd->target; + scb->lun = scb->scsi_cmd->lun; scb->sg_len = 0; scb->data_len = 0; scb->flags = 0; @@ -1391,9 +1755,9 @@ scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb); /* we don't support DCDB/READ/WRITE Scatter Gather */ - if ((scb->cmd.basic_io.op_code == READ_SCATTER_GATHER) || - (scb->cmd.basic_io.op_code == WRITE_SCATTER_GATHER) || - (scb->cmd.basic_io.op_code == DIRECT_CDB_SCATTER_GATHER)) + if ((scb->cmd.basic_io.op_code == IPS_CMD_READ_SG) || + (scb->cmd.basic_io.op_code == IPS_CMD_WRITE_SG) || + (scb->cmd.basic_io.op_code == IPS_CMD_DCDB_SG)) return (0); if (pt->CmdBSize) { @@ -1402,13 +1766,129 @@ scb->data_busaddr = 0L; } + if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB) + scb->cmd.dcdb.dcdb_address = VIRT_TO_BUS(&scb->dcdb); + if (pt->CmdBSize) { - if (scb->cmd.dcdb.op_code == DIRECT_CDB) { - scb->cmd.dcdb.dcdb_address = VIRT_TO_BUS(&scb->dcdb); + if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB) scb->dcdb.buffer_pointer = scb->data_busaddr; - } else { + else scb->cmd.basic_io.sg_addr = scb->data_busaddr; + } + + /* set timeouts */ + if (pt->TimeOut) { + scb->timeout = pt->TimeOut; + + if (pt->TimeOut <= 10) + scb->dcdb.cmd_attribute |= IPS_TIMEOUT10; + else if (pt->TimeOut <= 60) + scb->dcdb.cmd_attribute |= IPS_TIMEOUT60; + else + scb->dcdb.cmd_attribute |= IPS_TIMEOUT20M; + } + + /* assume success */ + scb->scsi_cmd->result = DID_OK << 16; + + /* success */ + return (1); +} + +/****************************************************************************/ +/* */ +/* Routine Name: ips_newusrcmd */ +/* */ +/* Routine Description: */ +/* */ +/* Process a user command and make it ready to send */ +/* */ +/****************************************************************************/ +static int +ips_newusrcmd(ips_ha_t *ha, ips_passthru_t *pt, ips_scb_t *scb) { + IPS_SG_LIST *sg_list; + char *user_area; + char *kern_area; + u32 datasize; + + DBG("ips_usrcmd"); + + if ((!scb) || (!pt) || (!ha)) + return (0); + + /* Save the S/G list pointer so it doesn't get clobbered */ + sg_list = scb->sg_list; + + /* copy in the CP */ + memcpy(&scb->cmd, &pt->CoppCP.cmd, sizeof(IPS_IOCTL_CMD)); + memcpy(&scb->dcdb, &pt->CoppCP.dcdb, sizeof(IPS_DCDB_TABLE)); + + /* FIX stuff that might be wrong */ + scb->sg_list = sg_list; + scb->scb_busaddr = VIRT_TO_BUS(scb); + scb->bus = scb->scsi_cmd->channel; + scb->target_id = scb->scsi_cmd->target; + scb->lun = scb->scsi_cmd->lun; + scb->sg_len = 0; + scb->data_len = 0; + scb->flags = 0; + scb->op_code = 0; + scb->callback = ipsintr_done; + scb->timeout = ips_cmd_timeout; + scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb); + + /* we don't support DCDB/READ/WRITE Scatter Gather */ + if ((scb->cmd.basic_io.op_code == IPS_CMD_READ_SG) || + (scb->cmd.basic_io.op_code == IPS_CMD_WRITE_SG) || + (scb->cmd.basic_io.op_code == IPS_CMD_DCDB_SG)) + return (0); + + if (pt->CmdBSize) { + if (pt->CmdBSize > ha->ioctl_datasize) { + void *bigger_struct; + + /* try to allocate a bigger struct */ + bigger_struct = kmalloc(pt->CmdBSize, GFP_KERNEL|GFP_DMA); + if (bigger_struct) { + /* free the old memory */ + kfree(ha->ioctl_data); + + /* use the new memory */ + ha->ioctl_data = bigger_struct; + ha->ioctl_datasize = pt->CmdBSize; + } else + return (0); + + } + + scb->data_busaddr = VIRT_TO_BUS(ha->ioctl_data); + + /* Attempt to copy in the data */ + user_area = *((char **) &scb->scsi_cmd->cmnd[4]); + kern_area = ha->ioctl_data; + datasize = *((u32 *) &scb->scsi_cmd->cmnd[8]); + + if (copy_from_user(kern_area, user_area, datasize) > 0) { +#if IPS_DEBUG_PT >= 1 + printk(KERN_NOTICE "(%s%d) passthru failed - unable to copy in user data\n", + ips_name, ha->host_num); +#endif + + return (0); } + + } else { + scb->data_busaddr = 0L; + } + + if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB) + scb->cmd.dcdb.dcdb_address = VIRT_TO_BUS(&scb->dcdb); + + if (pt->CmdBSize) { + if (scb->cmd.dcdb.op_code == IPS_CMD_DCDB) + scb->dcdb.buffer_pointer = scb->data_busaddr; + else + scb->cmd.basic_io.sg_addr = scb->data_busaddr; } /* set timeouts */ @@ -1416,15 +1896,15 @@ scb->timeout = pt->TimeOut; if (pt->TimeOut <= 10) - scb->dcdb.cmd_attribute |= TIMEOUT_10; + scb->dcdb.cmd_attribute |= IPS_TIMEOUT10; else if (pt->TimeOut <= 60) - scb->dcdb.cmd_attribute |= TIMEOUT_60; + scb->dcdb.cmd_attribute |= IPS_TIMEOUT60; else - scb->dcdb.cmd_attribute |= TIMEOUT_20M; + scb->dcdb.cmd_attribute |= IPS_TIMEOUT20M; } - /* assume error */ - scb->scsi_cmd->result = DID_ERROR << 16; + /* assume success */ + scb->scsi_cmd->result = DID_OK << 16; /* success */ return (1); @@ -1440,7 +1920,7 @@ /* */ /****************************************************************************/ static void -ips_cleanup_passthru(ips_scb_t *scb) { +ips_cleanup_passthru(ips_ha_t *ha, ips_scb_t *scb) { ips_passthru_t *pt; DBG("ips_cleanup_passthru"); @@ -1456,10 +1936,15 @@ pt = (ips_passthru_t *) scb->scsi_cmd->request_buffer; /* Copy data back to the user */ - pt->BasicStatus = scb->basic_status; - pt->ExtendedStatus = scb->extended_status; - - scb->scsi_cmd->result = DID_OK << 16; + if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_COMMAND) { + /* Copy data back to the user */ + pt->BasicStatus = scb->basic_status; + pt->ExtendedStatus = scb->extended_status; + } else { + pt->BasicStatus = scb->basic_status; + pt->ExtendedStatus = scb->extended_status; + up(scb->sem); + } } #endif @@ -1475,7 +1960,7 @@ /****************************************************************************/ static int ips_host_info(ips_ha_t *ha, char *ptr, off_t offset, int len) { - INFOSTR info; + IPS_INFOSTR info; DBG("ips_host_info"); @@ -1486,7 +1971,7 @@ copy_info(&info, "\nIBM ServeRAID General Information:\n\n"); - if ((ha->nvram->signature == NVRAM_PAGE5_SIGNATURE) && + if ((ha->nvram->signature == IPS_NVRAM_P5_SIG) && (ha->nvram->adapter_type != 0)) copy_info(&info, "\tController Type : %s\n", ips_adapter_name[ha->ad_type-1]); else @@ -1495,7 +1980,7 @@ copy_info(&info, "\tIO port address : 0x%lx\n", ha->io_addr); copy_info(&info, "\tIRQ number : %d\n", ha->irq); - if (ha->nvram->signature == NVRAM_PAGE5_SIGNATURE) + if (ha->nvram->signature == IPS_NVRAM_P5_SIG) copy_info(&info, "\tBIOS Version : %c%c%c%c%c%c%c%c\n", ha->nvram->bios_high[0], ha->nvram->bios_high[1], ha->nvram->bios_high[2], ha->nvram->bios_high[3], @@ -1541,11 +2026,11 @@ /* */ /* Routine Description: */ /* */ -/* Copy data into an INFOSTR structure */ +/* Copy data into an IPS_INFOSTR structure */ /* */ /****************************************************************************/ static void -copy_mem_info(INFOSTR *info, char *data, int len) { +copy_mem_info(IPS_INFOSTR *info, char *data, int len) { DBG("copy_mem_info"); if (info->pos + len > info->length) @@ -1577,7 +2062,7 @@ /* */ /****************************************************************************/ static int -copy_info(INFOSTR *info, char *fmt, ...) { +copy_info(IPS_INFOSTR *info, char *fmt, ...) { va_list args; char buf[81]; int len; @@ -1616,11 +2101,15 @@ /* initialize status queue */ ips_statinit(ha); + ha->reset_count = 1; + /* Setup HBA ID's */ - if (!ips_read_config(ha)) { + if (!ips_read_config(ha, IPS_INTR_IORL)) { #ifndef NO_IPS_RESET + ha->reset_count++; + /* Try to reset the controller and try again */ if (!ips_reset_adapter(ha)) { printk(KERN_WARNING "(%s%d) unable to reset controller.\n", @@ -1629,7 +2118,7 @@ return (0); } - if (!ips_clear_adapter(ha)) { + if (!ips_clear_adapter(ha, IPS_INTR_IORL)) { printk(KERN_WARNING "(%s%d) unable to initialize controller.\n", ips_name, ha->host_num); @@ -1638,7 +2127,7 @@ #endif - if (!ips_read_config(ha)) { + if (!ips_read_config(ha, IPS_INTR_IORL)) { printk(KERN_WARNING "(%s%d) unable to read config from controller.\n", ips_name, ha->host_num); @@ -1647,31 +2136,40 @@ } /* end if */ /* write driver version */ - if (!ips_write_driver_status(ha)) { + if (!ips_write_driver_status(ha, IPS_INTR_IORL)) { printk(KERN_WARNING "(%s%d) unable to write driver info to controller.\n", ips_name, ha->host_num); return (0); } - if (!ips_read_adapter_status(ha)) { + if (!ips_read_adapter_status(ha, IPS_INTR_IORL)) { printk(KERN_WARNING "(%s%d) unable to read controller status.\n", ips_name, ha->host_num); return (0); } - if (!ips_read_subsystem_parameters(ha)) { + if (!ips_read_subsystem_parameters(ha, IPS_INTR_IORL)) { printk(KERN_WARNING "(%s%d) unable to read subsystem parameters.\n", ips_name, ha->host_num); return (0); } + /* FFDC */ + if (ha->subsys->param[3] & 0x300000) { + struct timeval tv; + + do_gettimeofday(&tv); + ha->last_ffdc = tv.tv_sec; + ips_ffdc_reset(ha, IPS_INTR_IORL); + } + /* set limits on SID, LUN, BUS */ - ha->ntargets = MAX_TARGETS + 1; + ha->ntargets = IPS_MAX_TARGETS + 1; ha->nlun = 1; - ha->nbus = (ha->enq->ucMaxPhysicalDevices / MAX_TARGETS); + ha->nbus = (ha->enq->ucMaxPhysicalDevices / IPS_MAX_TARGETS); switch (ha->conf->logical_drive[0].ucStripeSize) { case 4: @@ -1736,21 +2234,55 @@ /* */ /* Take the next command off the queue and send it to the controller */ /* */ -/* ASSUMED to be called from within a lock */ -/* */ /****************************************************************************/ static void -ips_next(ips_ha_t *ha) { - ips_scb_t *scb; - Scsi_Cmnd *SC; - Scsi_Cmnd *p; - int ret; +ips_next(ips_ha_t *ha, int intr) { + ips_scb_t *scb; + Scsi_Cmnd *SC; + Scsi_Cmnd *p; + ips_copp_wait_item_t *item; + int ret; + int intr_status; + u32 cpu_flags; + u32 cpu_flags2; DBG("ips_next"); if (!ha) return ; + /* + * 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); + intr_status = IPS_INTR_IORL; + } else { + intr_status = intr; + + /* Quiet the compiler */ + cpu_flags2 = 0; + } + + if (ha->subsys->param[3] & 0x300000) { + struct timeval tv; + + do_gettimeofday(&tv); + + IPS_HA_LOCK(cpu_flags); + if (tv.tv_sec - ha->last_ffdc > IPS_SECS_8HOURS) { + ha->last_ffdc = tv.tv_sec; + IPS_HA_UNLOCK(cpu_flags); + ips_ffdc_time(ha, intr_status); + } else { + IPS_HA_UNLOCK(cpu_flags); + } + } + + if (intr == IPS_INTR_ON) + spin_unlock_irqrestore(&io_request_lock, cpu_flags2); + #ifndef NO_IPS_CMDLINE /* * Send passthru commands @@ -1759,32 +2291,50 @@ * since we limit the number that can be active * on the card at any one time */ + IPS_HA_LOCK(cpu_flags); + IPS_QUEUE_LOCK(&ha->copp_waitlist); while ((ha->num_ioctl < IPS_MAX_IOCTL) && (ha->copp_waitlist.head) && (scb = ips_getscb(ha))) { - SC = ips_removeq_wait_head(&ha->copp_waitlist); - ret = ips_make_passthru(ha, SC, scb); + IPS_QUEUE_UNLOCK(&ha->copp_waitlist); + IPS_HA_UNLOCK(cpu_flags); + item = ips_removeq_copp_head(&ha->copp_waitlist); + scb->scsi_cmd = item->scsi_cmd; + scb->sem = item->sem; + kfree(item); + + ret = ips_make_passthru(ha, scb->scsi_cmd, scb); switch (ret) { case IPS_FAILURE: if (scb->scsi_cmd) { + /* raise the semaphore */ + if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_NEW_COMMAND) + up(scb->sem); + scb->scsi_cmd->result = DID_ERROR << 16; - scb->scsi_cmd->scsi_done(scb->scsi_cmd); } ips_freescb(ha, scb); break; case IPS_SUCCESS_IMM: - if (scb->scsi_cmd) - scb->scsi_cmd->scsi_done(scb->scsi_cmd); + if (scb->scsi_cmd) { + /* raise the semaphore */ + if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_NEW_COMMAND) + up(scb->sem); + } + ips_freescb(ha, scb); break; default: break; } /* end case */ - if (ret != IPS_SUCCESS) + if (ret != IPS_SUCCESS) { + IPS_HA_LOCK(cpu_flags); + IPS_QUEUE_LOCK(&ha->copp_waitlist); continue; + } ret = ips_send_cmd(ha, scb); @@ -1796,27 +2346,43 @@ switch(ret) { case IPS_FAILURE: if (scb->scsi_cmd) { + /* raise the semaphore */ + if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_NEW_COMMAND) + up(scb->sem); + scb->scsi_cmd->result = DID_ERROR << 16; - scb->scsi_cmd->scsi_done(scb->scsi_cmd); } ips_freescb(ha, scb); break; case IPS_SUCCESS_IMM: - if (scb->scsi_cmd) - scb->scsi_cmd->scsi_done(scb->scsi_cmd); + if (scb->scsi_cmd) { + /* raise the semaphore */ + if (scb->scsi_cmd->cmnd[0] == IPS_IOCTL_NEW_COMMAND) + up(scb->sem); + } + ips_freescb(ha, scb); break; default: break; } /* end case */ + + IPS_HA_LOCK(cpu_flags); + IPS_QUEUE_LOCK(&ha->copp_waitlist); } + + IPS_QUEUE_UNLOCK(&ha->copp_waitlist); + IPS_HA_UNLOCK(cpu_flags); #endif /* * Send "Normal" I/O commands */ + IPS_HA_LOCK(cpu_flags); + IPS_QUEUE_LOCK(&ha->scb_waitlist); p = ha->scb_waitlist.head; + IPS_QUEUE_UNLOCK(&ha->scb_waitlist); while ((p) && (scb = ips_getscb(ha))) { if ((p->channel > 0) && (ha->dcdb_active[p->channel-1] & (1 << p->target))) { ips_freescb(ha, scb); @@ -1824,6 +2390,8 @@ continue; } + IPS_HA_UNLOCK(cpu_flags); + SC = ips_removeq_wait(&ha->scb_waitlist, p); SC->result = DID_OK; @@ -1904,7 +2472,7 @@ scb->dcdb.transfer_length = 0; if (scb->data_len >= IPS_MAX_XFER) { - scb->dcdb.cmd_attribute |= TRANSFER_64K; + scb->dcdb.cmd_attribute |= IPS_TRANSFER64K; scb->dcdb.transfer_length = 0; } @@ -1939,7 +2507,11 @@ } /* end case */ p = (Scsi_Cmnd *) p->host_scribble; + + IPS_HA_LOCK(cpu_flags); } /* end while */ + + IPS_HA_UNLOCK(cpu_flags); } /****************************************************************************/ @@ -1960,6 +2532,8 @@ if (!item) return ; + IPS_QUEUE_LOCK(queue); + item->q_next = queue->head; queue->head = item; @@ -1967,6 +2541,8 @@ queue->tail = item; queue->count++; + + IPS_QUEUE_UNLOCK(queue); } /****************************************************************************/ @@ -1987,6 +2563,8 @@ if (!item) return ; + IPS_QUEUE_LOCK(queue); + item->q_next = NULL; if (queue->tail) @@ -1998,6 +2576,8 @@ queue->head = item; queue->count++; + + IPS_QUEUE_UNLOCK(queue); } /****************************************************************************/ @@ -2017,10 +2597,15 @@ DBG("ips_removeq_scb_head"); + IPS_QUEUE_LOCK(queue); + item = queue->head; - if (!item) + if (!item) { + IPS_QUEUE_UNLOCK(queue); + return (NULL); + } queue->head = item->q_next; item->q_next = NULL; @@ -2030,6 +2615,8 @@ queue->count--; + IPS_QUEUE_UNLOCK(queue); + return (item); } @@ -2048,38 +2635,206 @@ ips_removeq_scb(ips_scb_queue_t *queue, ips_scb_t *item) { ips_scb_t *p; - DBG("ips_removeq_scb"); + DBG("ips_removeq_scb"); + + if (!item) + return (NULL); + + IPS_QUEUE_LOCK(queue); + + if (item == queue->head) { + IPS_QUEUE_UNLOCK(queue); + + return (ips_removeq_scb_head(queue)); + } + + p = queue->head; + + while ((p) && (item != p->q_next)) + p = p->q_next; + + if (p) { + /* found a match */ + p->q_next = item->q_next; + + if (!item->q_next) + queue->tail = p; + + item->q_next = NULL; + queue->count--; + + IPS_QUEUE_UNLOCK(queue); + + return (item); + } + + IPS_QUEUE_UNLOCK(queue); + + return (NULL); +} + +/****************************************************************************/ +/* */ +/* Routine Name: ips_putq_wait_head */ +/* */ +/* Routine Description: */ +/* */ +/* Add an item to the head of the queue */ +/* */ +/* ASSUMED to be called from within a lock */ +/* */ +/****************************************************************************/ +static inline void +ips_putq_wait_head(ips_wait_queue_t *queue, Scsi_Cmnd *item) { + DBG("ips_putq_wait_head"); + + if (!item) + return ; + + IPS_QUEUE_LOCK(queue); + + item->host_scribble = (char *) queue->head; + queue->head = item; + + if (!queue->tail) + queue->tail = item; + + queue->count++; + + IPS_QUEUE_UNLOCK(queue); +} + +/****************************************************************************/ +/* */ +/* Routine Name: ips_putq_wait_tail */ +/* */ +/* Routine Description: */ +/* */ +/* Add an item to the tail of the queue */ +/* */ +/* ASSUMED to be called from within a lock */ +/* */ +/****************************************************************************/ +static inline void +ips_putq_wait_tail(ips_wait_queue_t *queue, Scsi_Cmnd *item) { + DBG("ips_putq_wait_tail"); + + if (!item) + return ; + + IPS_QUEUE_LOCK(queue); + + item->host_scribble = NULL; + + if (queue->tail) + queue->tail->host_scribble = (char *)item; + + queue->tail = item; + + if (!queue->head) + queue->head = item; + + queue->count++; + + IPS_QUEUE_UNLOCK(queue); +} + +/****************************************************************************/ +/* */ +/* Routine Name: ips_removeq_wait_head */ +/* */ +/* Routine Description: */ +/* */ +/* Remove the head of the queue */ +/* */ +/* ASSUMED to be called from within a lock */ +/* */ +/****************************************************************************/ +static inline Scsi_Cmnd * +ips_removeq_wait_head(ips_wait_queue_t *queue) { + Scsi_Cmnd *item; + + DBG("ips_removeq_wait_head"); + + IPS_QUEUE_LOCK(queue); + + item = queue->head; + + if (!item) { + IPS_QUEUE_UNLOCK(queue); + + return (NULL); + } + + queue->head = (Scsi_Cmnd *) item->host_scribble; + item->host_scribble = NULL; + + if (queue->tail == item) + queue->tail = NULL; + + queue->count--; + + IPS_QUEUE_UNLOCK(queue); + + return (item); +} + +/****************************************************************************/ +/* */ +/* Routine Name: ips_removeq_wait */ +/* */ +/* Routine Description: */ +/* */ +/* Remove an item from a queue */ +/* */ +/* ASSUMED to be called from within a lock */ +/* */ +/****************************************************************************/ +static inline Scsi_Cmnd * +ips_removeq_wait(ips_wait_queue_t *queue, Scsi_Cmnd *item) { + Scsi_Cmnd *p; + + DBG("ips_removeq_wait"); if (!item) return (NULL); - if (item == queue->head) - return (ips_removeq_scb_head(queue)); + IPS_QUEUE_LOCK(queue); + + if (item == queue->head) { + IPS_QUEUE_UNLOCK(queue); + + return (ips_removeq_wait_head(queue)); + } p = queue->head; - while ((p) && (item != p->q_next)) - p = p->q_next; + while ((p) && (item != (Scsi_Cmnd *) p->host_scribble)) + p = (Scsi_Cmnd *) p->host_scribble; if (p) { /* found a match */ - p->q_next = item->q_next; + p->host_scribble = item->host_scribble; - if (!item->q_next) + if (!item->host_scribble) queue->tail = p; - item->q_next = NULL; + item->host_scribble = NULL; queue->count--; + IPS_QUEUE_UNLOCK(queue); + return (item); } + IPS_QUEUE_UNLOCK(queue); + return (NULL); } /****************************************************************************/ /* */ -/* Routine Name: ips_putq_wait_head */ +/* Routine Name: ips_putq_copp_head */ /* */ /* Routine Description: */ /* */ @@ -2089,24 +2844,28 @@ /* */ /****************************************************************************/ static inline void -ips_putq_wait_head(ips_wait_queue_t *queue, Scsi_Cmnd *item) { - DBG("ips_putq_wait_head"); +ips_putq_copp_head(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) { + DBG("ips_putq_copp_head"); if (!item) return ; - item->host_scribble = (char *) queue->head; + IPS_QUEUE_LOCK(queue); + + item->next = queue->head; queue->head = item; if (!queue->tail) queue->tail = item; queue->count++; + + IPS_QUEUE_UNLOCK(queue); } /****************************************************************************/ /* */ -/* Routine Name: ips_putq_wait_tail */ +/* Routine Name: ips_putq_copp_tail */ /* */ /* Routine Description: */ /* */ @@ -2116,16 +2875,18 @@ /* */ /****************************************************************************/ static inline void -ips_putq_wait_tail(ips_wait_queue_t *queue, Scsi_Cmnd *item) { - DBG("ips_putq_wait_tail"); +ips_putq_copp_tail(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) { + DBG("ips_putq_copp_tail"); if (!item) return ; - item->host_scribble = NULL; + IPS_QUEUE_LOCK(queue); + + item->next = NULL; if (queue->tail) - queue->tail->host_scribble = (char *)item; + queue->tail->next = item; queue->tail = item; @@ -2133,11 +2894,13 @@ queue->head = item; queue->count++; + + IPS_QUEUE_UNLOCK(queue); } /****************************************************************************/ /* */ -/* Routine Name: ips_removeq_wait_head */ +/* Routine Name: ips_removeq_copp_head */ /* */ /* Routine Description: */ /* */ @@ -2146,31 +2909,38 @@ /* ASSUMED to be called from within a lock */ /* */ /****************************************************************************/ -static inline Scsi_Cmnd * -ips_removeq_wait_head(ips_wait_queue_t *queue) { - Scsi_Cmnd *item; +static inline ips_copp_wait_item_t * +ips_removeq_copp_head(ips_copp_queue_t *queue) { + ips_copp_wait_item_t *item; - DBG("ips_removeq_wait_head"); + DBG("ips_removeq_copp_head"); + + IPS_QUEUE_LOCK(queue); item = queue->head; - if (!item) + if (!item) { + IPS_QUEUE_UNLOCK(queue); + return (NULL); + } - queue->head = (Scsi_Cmnd *) item->host_scribble; - item->host_scribble = NULL; + queue->head = item->next; + item->next = NULL; if (queue->tail == item) queue->tail = NULL; queue->count--; + IPS_QUEUE_UNLOCK(queue); + return (item); } /****************************************************************************/ /* */ -/* Routine Name: ips_removeq_wait */ +/* Routine Name: ips_removeq_copp */ /* */ /* Routine Description: */ /* */ @@ -2179,36 +2949,45 @@ /* ASSUMED to be called from within a lock */ /* */ /****************************************************************************/ -static inline Scsi_Cmnd * -ips_removeq_wait(ips_wait_queue_t *queue, Scsi_Cmnd *item) { - Scsi_Cmnd *p; +static inline ips_copp_wait_item_t * +ips_removeq_copp(ips_copp_queue_t *queue, ips_copp_wait_item_t *item) { + ips_copp_wait_item_t *p; - DBG("ips_removeq_wait"); + DBG("ips_removeq_copp"); if (!item) return (NULL); - if (item == queue->head) - return (ips_removeq_wait_head(queue)); + IPS_QUEUE_LOCK(queue); + + if (item == queue->head) { + IPS_QUEUE_UNLOCK(queue); + + return (ips_removeq_copp_head(queue)); + } p = queue->head; - while ((p) && (item != (Scsi_Cmnd *) p->host_scribble)) - p = (Scsi_Cmnd *) p->host_scribble; + while ((p) && (item != p->next)) + p = p->next; if (p) { /* found a match */ - p->host_scribble = item->host_scribble; + p->next = item->next; - if (!item->host_scribble) + if (!item->next) queue->tail = p; - item->host_scribble = NULL; + item->next = NULL; queue->count--; + IPS_QUEUE_UNLOCK(queue); + return (item); } + IPS_QUEUE_UNLOCK(queue); + return (NULL); } @@ -2269,6 +3048,7 @@ static void ips_done(ips_ha_t *ha, ips_scb_t *scb) { int ret; + u32 cpu_flags; DBG("ips_done"); @@ -2277,8 +3057,10 @@ #ifndef NO_IPS_CMDLINE if ((scb->scsi_cmd) && (ips_is_passthru(scb->scsi_cmd))) { - ips_cleanup_passthru(scb); + ips_cleanup_passthru(ha, scb); + IPS_HA_LOCK(cpu_flags); ha->num_ioctl--; + IPS_HA_UNLOCK(cpu_flags); } else { #endif /* @@ -2342,11 +3124,12 @@ scb->dcdb.cmd_attribute |= ips_command_direction[scb->scsi_cmd->cmnd[0]]; - + if (!scb->dcdb.cmd_attribute & 0x3) scb->dcdb.transfer_length = 0; + if (scb->data_len >= IPS_MAX_XFER) { - scb->dcdb.cmd_attribute |= TRANSFER_64K; + scb->dcdb.cmd_attribute |= IPS_TRANSFER64K; scb->dcdb.transfer_length = 0; } @@ -2379,15 +3162,17 @@ } /* end if passthru */ #endif - if (scb->bus) + if (scb->bus) { + IPS_HA_LOCK(cpu_flags); ha->dcdb_active[scb->bus-1] &= ~(1 << scb->target_id); + IPS_HA_UNLOCK(cpu_flags); + } /* call back to SCSI layer */ - scb->scsi_cmd->scsi_done(scb->scsi_cmd); - ips_freescb(ha, scb); + if (scb->scsi_cmd && scb->scsi_cmd->cmnd[0] != IPS_IOCTL_NEW_COMMAND) + scb->scsi_cmd->scsi_done(scb->scsi_cmd); - /* do the next command */ - ips_next(ha); + ips_freescb(ha, scb); } /****************************************************************************/ @@ -2426,19 +3211,19 @@ /* default driver error */ errcode = DID_ERROR; - switch (scb->basic_status & GSC_STATUS_MASK) { - case CMD_TIMEOUT: + switch (scb->basic_status & IPS_GSC_STATUS_MASK) { + case IPS_CMD_TIMEOUT: errcode = DID_TIME_OUT; break; - case INVAL_OPCO: - case INVAL_CMD_BLK: - case INVAL_PARM_BLK: - case LOG_DRV_ERROR: - case CMD_CMPLT_WERROR: + case IPS_INVAL_OPCO: + case IPS_INVAL_CMD_BLK: + case IPS_INVAL_PARM_BLK: + case IPS_LD_ERROR: + case IPS_CMD_CMPLT_WERROR: break; - case PHYS_DRV_ERROR: + case IPS_PHYS_DRV_ERROR: /* * For physical drive errors that * are not on a logical drive should @@ -2449,14 +3234,14 @@ errcode = DID_OK; switch (scb->extended_status) { - case SELECTION_TIMEOUT: + case IPS_ERR_SEL_TO: if (scb->bus) { scb->scsi_cmd->result |= DID_TIME_OUT << 16; return (0); } break; - case DATA_OVER_UNDER_RUN: + case IPS_ERR_OU_RUN: if ((scb->bus) && (scb->dcdb.transfer_length < scb->data_len)) { if ((scb->scsi_cmd->cmnd[0] == INQUIRY) && ((((char *) scb->scsi_cmd->buffer)[0] & 0x1f) == TYPE_DISK)) { @@ -2475,7 +3260,7 @@ } break; - case EXT_RECOVERY: + case IPS_ERR_RECOVERY: /* don't fail recovered errors */ if (scb->bus) { scb->scsi_cmd->result |= DID_OK << 16; @@ -2484,12 +3269,12 @@ } break; - case EXT_HOST_RESET: - case EXT_DEVICE_RESET: + case IPS_ERR_HOST_RESET: + case IPS_ERR_DEV_RESET: errcode = DID_RESET; break; - case EXT_CHECK_CONDITION: + case IPS_ERR_CKCOND: break; } /* end switch */ } /* end switch */ @@ -2509,7 +3294,7 @@ /* */ /****************************************************************************/ static int -ips_send(ips_ha_t *ha, ips_scb_t *scb, scb_callback callback) { +ips_send(ips_ha_t *ha, ips_scb_t *scb, ips_scb_callback callback) { int ret; DBG("ips_send"); @@ -2531,7 +3316,7 @@ /* */ /****************************************************************************/ static int -ips_send_wait(ips_ha_t *ha, ips_scb_t *scb, int timeout) { +ips_send_wait(ips_ha_t *ha, ips_scb_t *scb, int timeout, int intr) { int ret; DBG("ips_send_wait"); @@ -2544,7 +3329,7 @@ if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM)) return (ret); - ret = ips_wait(ha, timeout, IPS_INTR_OFF); + ret = ips_wait(ha, timeout, intr); return (ret); } @@ -2610,9 +3395,9 @@ scb->scsi_cmd->result = DID_OK << 16; if (scb->scsi_cmd->cmnd[0] == INQUIRY) { - IPS_INQUIRYDATA inq; + IPS_INQ_DATA inq; - memset(&inq, 0, sizeof(IPS_INQUIRYDATA)); + memset(&inq, 0, sizeof(IPS_INQ_DATA)); inq.DeviceType = TYPE_PROCESSOR; inq.DeviceTypeQualifier = 0; @@ -2628,7 +3413,7 @@ scb->scsi_cmd->result = DID_OK << 16; } } else { - scb->cmd.logical_info.op_code = GET_LOGICAL_DRIVE_INFO; + scb->cmd.logical_info.op_code = IPS_CMD_GET_LD_INFO; scb->cmd.logical_info.command_id = IPS_COMMAND_ID(ha, scb); scb->cmd.logical_info.buffer_addr = VIRT_TO_BUS(&ha->adapt->logical_drive_info); scb->cmd.logical_info.reserved = 0; @@ -2647,10 +3432,10 @@ case WRITE_6: if (!scb->sg_len) { scb->cmd.basic_io.op_code = - (scb->scsi_cmd->cmnd[0] == READ_6) ? IPS_READ : IPS_WRITE; + (scb->scsi_cmd->cmnd[0] == READ_6) ? IPS_CMD_READ : IPS_CMD_WRITE; } else { scb->cmd.basic_io.op_code = - (scb->scsi_cmd->cmnd[0] == READ_6) ? READ_SCATTER_GATHER : WRITE_SCATTER_GATHER; + (scb->scsi_cmd->cmnd[0] == READ_6) ? IPS_CMD_READ_SG : IPS_CMD_WRITE_SG; } scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb); @@ -2678,10 +3463,10 @@ case WRITE_10: if (!scb->sg_len) { scb->cmd.basic_io.op_code = - (scb->scsi_cmd->cmnd[0] == READ_10) ? IPS_READ : IPS_WRITE; + (scb->scsi_cmd->cmnd[0] == READ_10) ? IPS_CMD_READ : IPS_CMD_WRITE; } else { scb->cmd.basic_io.op_code = - (scb->scsi_cmd->cmnd[0] == READ_10) ? READ_SCATTER_GATHER : WRITE_SCATTER_GATHER; + (scb->scsi_cmd->cmnd[0] == READ_10) ? IPS_CMD_READ_SG : IPS_CMD_WRITE_SG; } scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb); @@ -2719,14 +3504,14 @@ break; case MODE_SENSE: - scb->cmd.basic_io.op_code = ENQUIRY; + scb->cmd.basic_io.op_code = IPS_CMD_ENQUIRY; scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb); scb->cmd.basic_io.sg_addr = VIRT_TO_BUS(ha->enq); ret = IPS_SUCCESS; break; case READ_CAPACITY: - scb->cmd.logical_info.op_code = GET_LOGICAL_DRIVE_INFO; + scb->cmd.logical_info.op_code = IPS_CMD_GET_LD_INFO; scb->cmd.logical_info.command_id = IPS_COMMAND_ID(ha, scb); scb->cmd.logical_info.buffer_addr = VIRT_TO_BUS(&ha->adapt->logical_drive_info); scb->cmd.logical_info.reserved = 0; @@ -2758,9 +3543,9 @@ /* setup DCDB */ if (scb->bus > 0) { if (!scb->sg_len) - scb->cmd.dcdb.op_code = DIRECT_CDB; + scb->cmd.dcdb.op_code = IPS_CMD_DCDB; else - scb->cmd.dcdb.op_code = DIRECT_CDB_SCATTER_GATHER; + scb->cmd.dcdb.op_code = IPS_CMD_DCDB_SG; ha->dcdb_active[scb->bus-1] |= (1 << scb->target_id); scb->cmd.dcdb.command_id = IPS_COMMAND_ID(ha, scb); @@ -2770,19 +3555,19 @@ scb->cmd.dcdb.reserved3 = 0; scb->dcdb.device_address = ((scb->bus - 1) << 4) | scb->target_id; - scb->dcdb.cmd_attribute |= DISCONNECT_ALLOWED; + scb->dcdb.cmd_attribute |= IPS_DISCONNECT_ALLOWED; if (scb->timeout) { if (scb->timeout <= 10) - scb->dcdb.cmd_attribute |= TIMEOUT_10; + scb->dcdb.cmd_attribute |= IPS_TIMEOUT10; else if (scb->timeout <= 60) - scb->dcdb.cmd_attribute |= TIMEOUT_60; + scb->dcdb.cmd_attribute |= IPS_TIMEOUT60; else - scb->dcdb.cmd_attribute |= TIMEOUT_20M; + scb->dcdb.cmd_attribute |= IPS_TIMEOUT20M; } - if (!(scb->dcdb.cmd_attribute & TIMEOUT_20M)) - scb->dcdb.cmd_attribute |= TIMEOUT_20M; + if (!(scb->dcdb.cmd_attribute & IPS_TIMEOUT20M)) + scb->dcdb.cmd_attribute |= IPS_TIMEOUT20M; scb->dcdb.sense_length = sizeof(scb->scsi_cmd->sense_buffer); scb->dcdb.buffer_pointer = scb->data_busaddr; @@ -2817,7 +3602,7 @@ command_id = ips_statupd(ha); - if (command_id > (MAX_CMDS-1)) { + if (command_id > (IPS_MAX_CMDS-1)) { printk(KERN_NOTICE "(%s%d) invalid command id received: %d\n", ips_name, ha->host_num, command_id); @@ -2827,7 +3612,7 @@ scb = &ha->scbs[command_id]; sp->scb_addr = (u32) scb; sp->residue_len = 0; - scb->basic_status = basic_status = ha->adapt->p_status_tail->basic_status & BASIC_STATUS_MASK; + scb->basic_status = basic_status = ha->adapt->p_status_tail->basic_status & IPS_BASIC_STATUS_MASK; scb->extended_status = ext_status = ha->adapt->p_status_tail->extended_status; /* Remove the item from the active queue */ @@ -2846,12 +3631,12 @@ errcode = DID_OK; ret = 0; - if (((basic_status & GSC_STATUS_MASK) == SSUCCESS) || - ((basic_status & GSC_STATUS_MASK) == RECOVERED_ERROR)) { + if (((basic_status & IPS_GSC_STATUS_MASK) == IPS_CMD_SUCCESS) || + ((basic_status & IPS_GSC_STATUS_MASK) == IPS_CMD_RECOVERED_ERROR)) { if (scb->bus == 0) { #if IPS_DEBUG >= 1 - if ((basic_status & GSC_STATUS_MASK) == RECOVERED_ERROR) { + if ((basic_status & IPS_GSC_STATUS_MASK) == IPS_CMD_RECOVERED_ERROR) { printk(KERN_NOTICE "(%s%d) Recovered Logical Drive Error OpCode: %x, BSB: %x, ESB: %x\n", ips_name, ha->host_num, scb->cmd.basic_io.op_code, basic_status, ext_status); @@ -2975,20 +3760,20 @@ ips_online(ips_ha_t *ha, ips_scb_t *scb) { DBG("ips_online"); - if (scb->target_id >= MAX_LOGICAL_DRIVES) + if (scb->target_id >= IPS_MAX_LD) return (0); - if ((scb->basic_status & GSC_STATUS_MASK) > 1) { + if ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1) { memset(&ha->adapt->logical_drive_info, 0, sizeof(ha->adapt->logical_drive_info)); return (0); } if (scb->target_id < ha->adapt->logical_drive_info.no_of_log_drive && - ha->adapt->logical_drive_info.drive_info[scb->target_id].state != OFF_LINE && - ha->adapt->logical_drive_info.drive_info[scb->target_id].state != FREE && - ha->adapt->logical_drive_info.drive_info[scb->target_id].state != CRS && - ha->adapt->logical_drive_info.drive_info[scb->target_id].state != SYS) + ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_OFFLINE && + ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_FREE && + ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_CRS && + ha->adapt->logical_drive_info.drive_info[scb->target_id].state != IPS_LD_SYS) return (1); else return (0); @@ -3005,11 +3790,11 @@ /****************************************************************************/ static int ips_inquiry(ips_ha_t *ha, ips_scb_t *scb) { - IPS_INQUIRYDATA inq; + IPS_INQ_DATA inq; DBG("ips_inquiry"); - memset(&inq, 0, sizeof(IPS_INQUIRYDATA)); + memset(&inq, 0, sizeof(IPS_INQ_DATA)); inq.DeviceType = TYPE_DISK; inq.DeviceTypeQualifier = 0; @@ -3036,14 +3821,14 @@ /****************************************************************************/ static int ips_rdcap(ips_ha_t *ha, ips_scb_t *scb) { - CAPACITY_T *cap; + IPS_CAPACITY *cap; DBG("ips_rdcap"); if (scb->scsi_cmd->bufflen < 8) return (0); - cap = (CAPACITY_T *) scb->scsi_cmd->request_buffer; + cap = (IPS_CAPACITY *) scb->scsi_cmd->request_buffer; cap->lba = htonl(ha->adapt->logical_drive_info.drive_info[scb->target_id].sector_count - 1); cap->len = htonl((u32) IPS_BLKSIZE); @@ -3071,11 +3856,11 @@ if (ha->enq->ulDriveSize[scb->target_id] > 0x400000 && (ha->enq->ucMiscFlag & 0x8) == 0) { - heads = NORM_MODE_HEADS; - sectors = NORM_MODE_SECTORS; + heads = IPS_NORM_HEADS; + sectors = IPS_NORM_SECTORS; } else { - heads = COMP_MODE_HEADS; - sectors = COMP_MODE_SECTORS; + heads = IPS_COMP_HEADS; + sectors = IPS_COMP_SECTORS; } cylinders = ha->enq->ulDriveSize[scb->target_id] / (heads * sectors); @@ -3088,7 +3873,7 @@ case 0x03: /* page 3 */ mdata.pdata.pg3.pg_pc = 0x3; mdata.pdata.pg3.pg_res1 = 0; - mdata.pdata.pg3.pg_len = sizeof(DADF_T); + mdata.pdata.pg3.pg_len = sizeof(IPS_DADF); mdata.plh.plh_len = 3 + mdata.plh.plh_bdl + mdata.pdata.pg3.pg_len; mdata.pdata.pg3.pg_trk_z = 0; mdata.pdata.pg3.pg_asec_z = 0; @@ -3110,7 +3895,7 @@ case 0x4: mdata.pdata.pg4.pg_pc = 0x4; mdata.pdata.pg4.pg_res1 = 0; - mdata.pdata.pg4.pg_len = sizeof(RDDG_T); + mdata.pdata.pg4.pg_len = sizeof(IPS_RDDG); mdata.plh.plh_len = 3 + mdata.plh.plh_bdl + mdata.pdata.pg4.pg_len; mdata.pdata.pg4.pg_cylu = (cylinders >> 8) & 0xffff; mdata.pdata.pg4.pg_cyll = cylinders & 0xff; @@ -3204,6 +3989,12 @@ ha->dummy = NULL; } + if (ha->ioctl_data) { + kfree(ha->ioctl_data); + ha->ioctl_data = NULL; + ha->ioctl_datasize = 0; + } + if (ha->scbs) { for (i = 0; i < ha->max_cmds; i++) { if (ha->scbs[i].sg_list) @@ -3241,7 +4032,7 @@ scb_p = &ha->scbs[i]; /* allocate S/G list */ - scb_p->sg_list = (SG_LIST *) kmalloc(sizeof(SG_LIST) * MAX_SG_ELEMENTS, GFP_KERNEL|GFP_DMA); + scb_p->sg_list = (IPS_SG_LIST *) kmalloc(sizeof(IPS_SG_LIST) * IPS_MAX_SG, GFP_KERNEL|GFP_DMA); if (! scb_p->sg_list) return (0); @@ -3268,7 +4059,7 @@ /****************************************************************************/ static void ips_init_scb(ips_ha_t *ha, ips_scb_t *scb) { - SG_LIST *sg_list; + IPS_SG_LIST *sg_list; DBG("ips_init_scb"); @@ -3279,19 +4070,19 @@ /* zero fill */ memset(scb, 0, sizeof(ips_scb_t)); - memset(ha->dummy, 0, sizeof(BASIC_IO_CMD)); + memset(ha->dummy, 0, sizeof(IPS_IO_CMD)); /* Initialize dummy command bucket */ ha->dummy->op_code = 0xFF; ha->dummy->ccsar = VIRT_TO_BUS(ha->dummy); - ha->dummy->command_id = MAX_CMDS; + ha->dummy->command_id = IPS_MAX_CMDS; /* set bus address of scb */ scb->scb_busaddr = VIRT_TO_BUS(scb); scb->sg_list = sg_list; /* Neptune Fix */ - scb->cmd.basic_io.cccr = ILE; + scb->cmd.basic_io.cccr = IPS_BIT_ILE; scb->cmd.basic_io.ccsar = VIRT_TO_BUS(ha->dummy); } @@ -3309,13 +4100,13 @@ static ips_scb_t * ips_getscb(ips_ha_t *ha) { ips_scb_t *scb; - unsigned int cpu_flags; + u32 cpu_flags; DBG("ips_getscb"); - spin_lock_irqsave(&ha->scb_lock, cpu_flags); + IPS_SCB_LOCK(cpu_flags); if ((scb = ha->scb_freelist) == NULL) { - spin_unlock_irqrestore(&ha->scb_lock, cpu_flags); + IPS_SCB_UNLOCK(cpu_flags); return (NULL); } @@ -3323,7 +4114,7 @@ ha->scb_freelist = scb->q_next; scb->q_next = NULL; - spin_unlock_irqrestore(&ha->scb_lock, cpu_flags); + IPS_SCB_UNLOCK(cpu_flags); ips_init_scb(ha, scb); @@ -3343,16 +4134,16 @@ /****************************************************************************/ static void ips_freescb(ips_ha_t *ha, ips_scb_t *scb) { - unsigned int cpu_flags; + u32 cpu_flags; DBG("ips_freescb"); /* check to make sure this is not our "special" scb */ if (IPS_COMMAND_ID(ha, scb) < (ha->max_cmds - 1)) { - spin_lock_irqsave(&ha->scb_lock, cpu_flags); + IPS_SCB_LOCK(cpu_flags); scb->q_next = ha->scb_freelist; ha->scb_freelist = scb; - spin_unlock_irqrestore(&ha->scb_lock, cpu_flags); + IPS_SCB_UNLOCK(cpu_flags); } } @@ -3369,10 +4160,11 @@ ips_reset_adapter(ips_ha_t *ha) { u8 Isr; u8 Cbsp; - u8 PostByte[MAX_POST_BYTES]; - u8 ConfigByte[MAX_CONFIG_BYTES]; + u8 PostByte[IPS_MAX_POST_BYTES]; + u8 ConfigByte[IPS_MAX_CONFIG_BYTES]; int i, j; int reset_counter; + u32 cpu_flags; DBG("ips_reset_adapter"); @@ -3381,108 +4173,125 @@ ha->io_addr, ha->irq); #endif + IPS_HA_LOCK(cpu_flags); + reset_counter = 0; while (reset_counter < 2) { reset_counter++; - outb(RST, ha->io_addr + SCPR); - MDELAY(ONE_SEC); - outb(0, ha->io_addr + SCPR); - MDELAY(ONE_SEC); + outb(IPS_BIT_RST, ha->io_addr + IPS_REG_SCPR); + MDELAY(IPS_ONE_SEC); + outb(0, ha->io_addr + IPS_REG_SCPR); + MDELAY(IPS_ONE_SEC); - for (i = 0; i < MAX_POST_BYTES; i++) { + for (i = 0; i < IPS_MAX_POST_BYTES; i++) { for (j = 0; j < 45; j++) { - Isr = inb(ha->io_addr + HISR); - if (Isr & GHI) + Isr = inb(ha->io_addr + IPS_REG_HISR); + if (Isr & IPS_BIT_GHI) break; - MDELAY(ONE_SEC); + MDELAY(IPS_ONE_SEC); } if (j >= 45) { /* error occured */ if (reset_counter < 2) continue; - else + else { /* reset failed */ + IPS_HA_UNLOCK(cpu_flags); + return (0); + } } - PostByte[i] = inb(ha->io_addr + ISPR); - outb(Isr, ha->io_addr + HISR); + PostByte[i] = inb(ha->io_addr + IPS_REG_ISPR); + outb(Isr, ha->io_addr + IPS_REG_HISR); } - if (PostByte[0] < GOOD_POST_BASIC_STATUS) { + if (PostByte[0] < IPS_GOOD_POST_STATUS) { printk("(%s%d) reset controller fails (post status %x %x).\n", ips_name, ha->host_num, PostByte[0], PostByte[1]); + IPS_HA_UNLOCK(cpu_flags); + return (0); } - for (i = 0; i < MAX_CONFIG_BYTES; i++) { + for (i = 0; i < IPS_MAX_CONFIG_BYTES; i++) { for (j = 0; j < 240; j++) { - Isr = inb(ha->io_addr + HISR); - if (Isr & GHI) + Isr = inb(ha->io_addr + IPS_REG_HISR); + if (Isr & IPS_BIT_GHI) break; - MDELAY(ONE_SEC); /* 100 msec */ + MDELAY(IPS_ONE_SEC); /* 100 msec */ } if (j >= 240) { /* error occured */ if (reset_counter < 2) continue; - else + else { /* reset failed */ + IPS_HA_UNLOCK(cpu_flags); + return (0); + } } - ConfigByte[i] = inb(ha->io_addr + ISPR); - outb(Isr, ha->io_addr + HISR); + ConfigByte[i] = inb(ha->io_addr + IPS_REG_ISPR); + outb(Isr, ha->io_addr + IPS_REG_HISR); } if (ConfigByte[0] == 0 && ConfigByte[1] == 2) { printk("(%s%d) reset controller fails (status %x %x).\n", ips_name, ha->host_num, ConfigByte[0], ConfigByte[1]); + IPS_HA_UNLOCK(cpu_flags); + return (0); } for (i = 0; i < 240; i++) { - Cbsp = inb(ha->io_addr + CBSP); + Cbsp = inb(ha->io_addr + IPS_REG_CBSP); - if ((Cbsp & OP) == 0) + if ((Cbsp & IPS_BIT_OP) == 0) break; - MDELAY(ONE_SEC); + MDELAY(IPS_ONE_SEC); } if (i >= 240) { /* error occured */ if (reset_counter < 2) continue; - else + else { /* reset failed */ + IPS_HA_UNLOCK(cpu_flags); + return (0); + } } /* setup CCCR */ - outw(0x1010, ha->io_addr + CCCR); + outw(0x1010, ha->io_addr + IPS_REG_CCCR); /* Enable busmastering */ - outb(EBM, ha->io_addr + SCPR); + outb(IPS_BIT_EBM, ha->io_addr + IPS_REG_SCPR); /* setup status queues */ ips_statinit(ha); /* Enable interrupts */ - outb(EI, ha->io_addr + HISR); + outb(IPS_BIT_EI, ha->io_addr + IPS_REG_HISR); /* if we get here then everything went OK */ break; } + IPS_HA_UNLOCK(cpu_flags); + return (1); } @@ -3502,14 +4311,14 @@ DBG("ips_statinit"); ha->adapt->p_status_start = ha->adapt->status; - ha->adapt->p_status_end = ha->adapt->status + MAX_CMDS; + ha->adapt->p_status_end = ha->adapt->status + IPS_MAX_CMDS; ha->adapt->p_status_tail = ha->adapt->status; phys_status_start = VIRT_TO_BUS(ha->adapt->status); - outl(phys_status_start, ha->io_addr + SQSR); - outl(phys_status_start + STATUS_Q_SIZE, ha->io_addr + SQER); - outl(phys_status_start + STATUS_SIZE, ha->io_addr + SQHR); - outl(phys_status_start, ha->io_addr + SQTR); + outl(phys_status_start, ha->io_addr + IPS_REG_SQSR); + outl(phys_status_start + IPS_STATUS_Q_SIZE, ha->io_addr + IPS_REG_SQER); + outl(phys_status_start + IPS_STATUS_SIZE, ha->io_addr + IPS_REG_SQHR); + outl(phys_status_start, ha->io_addr + IPS_REG_SQTR); ha->adapt->hw_status_start = phys_status_start; ha->adapt->hw_status_tail = phys_status_start; @@ -3532,13 +4341,13 @@ if (ha->adapt->p_status_tail != ha->adapt->p_status_end) { ha->adapt->p_status_tail++; - ha->adapt->hw_status_tail += sizeof(STATUS); + ha->adapt->hw_status_tail += sizeof(IPS_STATUS); } else { ha->adapt->p_status_tail = ha->adapt->p_status_start; ha->adapt->hw_status_tail = ha->adapt->hw_status_start; } - outl(ha->adapt->hw_status_tail, ha->io_addr + SQTR); + outl(ha->adapt->hw_status_tail, ha->io_addr + IPS_REG_SQTR); command_id = ha->adapt->p_status_tail->command_id; @@ -3560,6 +4369,7 @@ ips_issue(ips_ha_t *ha, ips_scb_t *scb) { u32 TimeOut; u16 val; + u32 cpu_flags; DBG("ips_issue"); @@ -3577,17 +4387,19 @@ ips_name, scb->cmd.basic_io.command_id); #if IPS_DEBUG >= 11 - MDELAY(ONE_SEC); + MDELAY(IPS_ONE_SEC); #endif #endif + IPS_HA_LOCK(cpu_flags); + TimeOut = 0; - while ((val = inw(ha->io_addr + CCCR)) & SEMAPHORE) { + while ((val = inw(ha->io_addr + IPS_REG_CCCR)) & IPS_BIT_SEM) { UDELAY(1000); - if (++TimeOut >= SEMAPHORE_TIMEOUT) { - if (!(val & START_STOP_BIT)) + if (++TimeOut >= IPS_SEM_TIMEOUT) { + if (!(val & IPS_BIT_START_STOP)) break; printk(KERN_WARNING "(%s%d) ips_issue val [0x%x].\n", @@ -3595,12 +4407,16 @@ printk(KERN_WARNING "(%s%d) ips_issue semaphore chk timeout.\n", ips_name, ha->host_num); + IPS_HA_UNLOCK(cpu_flags); + return (IPS_FAILURE); } /* end if */ } /* end while */ - outl(scb->scb_busaddr, ha->io_addr + CCSAR); - outw(START_COMMAND, ha->io_addr + CCCR); + outl(scb->scb_busaddr, ha->io_addr + IPS_REG_CCSAR); + outw(IPS_BIT_START_CMD, ha->io_addr + IPS_REG_CCCR); + + IPS_HA_UNLOCK(cpu_flags); return (IPS_SUCCESS); } @@ -3620,18 +4436,18 @@ DBG("ips_isintr"); - Isr = inb(ha->io_addr + HISR); + Isr = inb(ha->io_addr + IPS_REG_HISR); if (Isr == 0xFF) /* ?!?! Nothing really there */ return (0); - if (Isr & SCE) + if (Isr & IPS_BIT_SCE) return (1); - else if (Isr & (SQO | GHI)) { + else if (Isr & (IPS_BIT_SQO | IPS_BIT_GHI)) { /* status queue overflow or GHI */ /* just clear the interrupt */ - outb(Isr, ha->io_addr + HISR); + outb(Isr, ha->io_addr + IPS_REG_HISR); } return (0); @@ -3649,15 +4465,23 @@ static int ips_wait(ips_ha_t *ha, int time, int intr) { int ret; + u8 done; DBG("ips_wait"); ret = IPS_FAILURE; + done = FALSE; - time *= ONE_SEC; /* convert seconds to milliseconds */ + time *= IPS_ONE_SEC; /* convert seconds to milliseconds */ - while (time > 0) { - if (intr == IPS_INTR_OFF) { + while ((time > 0) && (!done)) { + if (intr == IPS_INTR_ON) { + if (ha->waitflag == FALSE) { + ret = IPS_SUCCESS; + done = TRUE; + break; + } + } else if (intr == IPS_INTR_IORL) { if (ha->waitflag == FALSE) { /* * controller generated an interupt to @@ -3665,28 +4489,50 @@ * and ips_intr() has serviced the interrupt. */ ret = IPS_SUCCESS; + done = TRUE; break; } /* - * NOTE: Interrupts are disabled here - * On an SMP system interrupts will only - * be disabled on one processor. - * So, ultimately we still need to set the - * "I'm in the interrupt handler flag" + * NOTE: we already have the io_request_lock so + * even if we get an interrupt it won't get serviced + * until after we finish. */ + while (test_and_set_bit(IPS_IN_INTR, &ha->flags)) UDELAY(1000); ips_intr(ha); clear_bit(IPS_IN_INTR, &ha->flags); - - } else { + } else if (intr == IPS_INTR_HAL) { if (ha->waitflag == FALSE) { + /* + * controller generated an interupt to + * acknowledge completion of the command + * and ips_intr() has serviced the interrupt. + */ ret = IPS_SUCCESS; + done = TRUE; break; } + + /* + * NOTE: since we were not called with the iorequest lock + * we must obtain it before we can call the interrupt handler. + * We were called under the HA lock so we can assume that interrupts + * are masked. + */ + spin_lock(&io_request_lock); + + while (test_and_set_bit(IPS_IN_INTR, &ha->flags)) + UDELAY(1000); + + ips_intr(ha); + + clear_bit(IPS_IN_INTR, &ha->flags); + + spin_unlock(&io_request_lock); } UDELAY(1000); /* 1 milisecond */ @@ -3706,10 +4552,10 @@ /* */ /****************************************************************************/ static int -ips_write_driver_status(ips_ha_t *ha) { +ips_write_driver_status(ips_ha_t *ha, int intr) { DBG("ips_write_driver_status"); - if (!ips_readwrite_page5(ha, FALSE)) { + if (!ips_readwrite_page5(ha, FALSE, intr)) { printk(KERN_WARNING "(%s%d) unable to read NVRAM page 5.\n", ips_name, ha->host_num); @@ -3718,7 +4564,7 @@ /* check to make sure the page has a valid */ /* signature */ - if (ha->nvram->signature != NVRAM_PAGE5_SIGNATURE) { + if (ha->nvram->signature != IPS_NVRAM_P5_SIG) { #if IPS_DEBUG >= 1 printk("(%s%d) NVRAM page 5 has an invalid signature: %X.\n", ips_name, ha->host_num, ha->nvram->signature); @@ -3739,12 +4585,12 @@ ha->ad_type = ha->nvram->adapter_type; /* change values (as needed) */ - ha->nvram->operating_system = OS_LINUX; + ha->nvram->operating_system = IPS_OS_LINUX; strncpy((char *) ha->nvram->driver_high, IPS_VERSION_HIGH, 4); strncpy((char *) ha->nvram->driver_low, IPS_VERSION_LOW, 4); /* now update the page */ - if (!ips_readwrite_page5(ha, TRUE)) { + if (!ips_readwrite_page5(ha, TRUE, intr)) { printk(KERN_WARNING "(%s%d) unable to write NVRAM page 5.\n", ips_name, ha->host_num); @@ -3764,7 +4610,7 @@ /* */ /****************************************************************************/ static int -ips_read_adapter_status(ips_ha_t *ha) { +ips_read_adapter_status(ips_ha_t *ha, int intr) { ips_scb_t *scb; int ret; @@ -3775,9 +4621,9 @@ ips_init_scb(ha, scb); scb->timeout = ips_cmd_timeout; - scb->cdb[0] = ENQUIRY; + scb->cdb[0] = IPS_CMD_ENQUIRY; - scb->cmd.basic_io.op_code = ENQUIRY; + scb->cmd.basic_io.op_code = IPS_CMD_ENQUIRY; scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb); scb->cmd.basic_io.sg_count = 0; scb->cmd.basic_io.sg_addr = VIRT_TO_BUS(ha->enq); @@ -3787,7 +4633,7 @@ scb->cmd.basic_io.reserved = 0; /* send command */ - ret = ips_send_wait(ha, scb, ips_cmd_timeout); + ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr); if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM)) return (0); @@ -3804,7 +4650,7 @@ /* */ /****************************************************************************/ static int -ips_read_subsystem_parameters(ips_ha_t *ha) { +ips_read_subsystem_parameters(ips_ha_t *ha, int intr) { ips_scb_t *scb; int ret; @@ -3815,9 +4661,9 @@ ips_init_scb(ha, scb); scb->timeout = ips_cmd_timeout; - scb->cdb[0] = GET_SUBSYS_PARAM; + scb->cdb[0] = IPS_CMD_GET_SUBSYS; - scb->cmd.basic_io.op_code = GET_SUBSYS_PARAM; + scb->cmd.basic_io.op_code = IPS_CMD_GET_SUBSYS; scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb); scb->cmd.basic_io.sg_count = 0; scb->cmd.basic_io.sg_addr = VIRT_TO_BUS(ha->subsys); @@ -3827,7 +4673,7 @@ scb->cmd.basic_io.reserved = 0; /* send command */ - ret = ips_send_wait(ha, scb, ips_cmd_timeout); + ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr); if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM)) return (0); @@ -3844,7 +4690,7 @@ /* */ /****************************************************************************/ static int -ips_read_config(ips_ha_t *ha) { +ips_read_config(ips_ha_t *ha, int intr) { ips_scb_t *scb; int i; int ret; @@ -3861,18 +4707,18 @@ ips_init_scb(ha, scb); scb->timeout = ips_cmd_timeout; - scb->cdb[0] = READ_NVRAM_CONFIGURATION; + scb->cdb[0] = IPS_CMD_READ_CONF; - scb->cmd.basic_io.op_code = READ_NVRAM_CONFIGURATION; + scb->cmd.basic_io.op_code = IPS_CMD_READ_CONF; scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb); scb->cmd.basic_io.sg_addr = VIRT_TO_BUS(ha->conf); /* send command */ - if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout)) == IPS_FAILURE) || + if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM) || - ((scb->basic_status & GSC_STATUS_MASK) > 1)) { + ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1)) { - memset(ha->conf, 0, sizeof(CONFCMD)); + memset(ha->conf, 0, sizeof(IPS_CONF)); /* reset initiator IDs */ ha->conf->init_id[0] = IPS_ADAPTER_ID; @@ -3891,11 +4737,11 @@ /* */ /* Routine Description: */ /* */ -/* Read the configuration on the adapter */ +/* Read nvram page 5 from the adapter */ /* */ /****************************************************************************/ static int -ips_readwrite_page5(ips_ha_t *ha, int write) { +ips_readwrite_page5(ips_ha_t *ha, int write, int intr) { ips_scb_t *scb; int ret; @@ -3906,9 +4752,9 @@ ips_init_scb(ha, scb); scb->timeout = ips_cmd_timeout; - scb->cdb[0] = RW_NVRAM_PAGE; + scb->cdb[0] = IPS_CMD_RW_NVRAM_PAGE; - scb->cmd.nvram.op_code = RW_NVRAM_PAGE; + scb->cmd.nvram.op_code = IPS_CMD_RW_NVRAM_PAGE; scb->cmd.nvram.command_id = IPS_COMMAND_ID(ha, scb); scb->cmd.nvram.page = 5; scb->cmd.nvram.write = write; @@ -3917,11 +4763,11 @@ scb->cmd.nvram.reserved2 = 0; /* issue the command */ - if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout)) == IPS_FAILURE) || + if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM) || - ((scb->basic_status & GSC_STATUS_MASK) > 1)) { + ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1)) { - memset(ha->nvram, 0, sizeof(NVRAM_PAGE5)); + memset(ha->nvram, 0, sizeof(IPS_NVRAM_P5)); return (0); } @@ -3939,7 +4785,7 @@ /* */ /****************************************************************************/ static int -ips_clear_adapter(ips_ha_t *ha) { +ips_clear_adapter(ips_ha_t *ha, int intr) { ips_scb_t *scb; int ret; @@ -3950,41 +4796,413 @@ ips_init_scb(ha, scb); scb->timeout = ips_reset_timeout; - scb->cdb[0] = CONFIG_SYNC; + scb->cdb[0] = IPS_CMD_CONFIG_SYNC; - scb->cmd.config_sync.op_code = CONFIG_SYNC; + scb->cmd.config_sync.op_code = IPS_CMD_CONFIG_SYNC; scb->cmd.config_sync.command_id = IPS_COMMAND_ID(ha, scb); scb->cmd.config_sync.channel = 0; - scb->cmd.config_sync.source_target = POCL; + scb->cmd.config_sync.source_target = IPS_POCL; scb->cmd.config_sync.reserved = 0; scb->cmd.config_sync.reserved2 = 0; scb->cmd.config_sync.reserved3 = 0; /* issue command */ - ret = ips_send_wait(ha, scb, ips_reset_timeout); + ret = ips_send_wait(ha, scb, ips_reset_timeout, intr); if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM)) return (0); /* send unlock stripe command */ ips_init_scb(ha, scb); - scb->cdb[0] = GET_ERASE_ERROR_TABLE; + scb->cdb[0] = IPS_CMD_ERROR_TABLE; scb->timeout = ips_reset_timeout; - scb->cmd.unlock_stripe.op_code = GET_ERASE_ERROR_TABLE; + scb->cmd.unlock_stripe.op_code = IPS_CMD_ERROR_TABLE; scb->cmd.unlock_stripe.command_id = IPS_COMMAND_ID(ha, scb); scb->cmd.unlock_stripe.log_drv = 0; - scb->cmd.unlock_stripe.control = CSL; + scb->cmd.unlock_stripe.control = IPS_CSL; scb->cmd.unlock_stripe.reserved = 0; scb->cmd.unlock_stripe.reserved2 = 0; scb->cmd.unlock_stripe.reserved3 = 0; /* issue command */ - ret = ips_send_wait(ha, scb, ips_reset_timeout); + ret = ips_send_wait(ha, scb, ips_reset_timeout, intr); if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM)) return (0); return (1); +} + +/****************************************************************************/ +/* */ +/* Routine Name: ips_ffdc_reset */ +/* */ +/* Routine Description: */ +/* */ +/* FFDC: write reset info */ +/* */ +/****************************************************************************/ +static void +ips_ffdc_reset(ips_ha_t *ha, int intr) { + ips_scb_t *scb; + + DBG("ips_ffdc_reset"); + + scb = &ha->scbs[ha->max_cmds-1]; + + ips_init_scb(ha, scb); + + scb->timeout = ips_cmd_timeout; + scb->cdb[0] = IPS_CMD_FFDC; + scb->cmd.ffdc.op_code = IPS_CMD_FFDC; + scb->cmd.ffdc.command_id = IPS_COMMAND_ID(ha, scb); + scb->cmd.ffdc.reset_count = ha->reset_count; + scb->cmd.ffdc.reset_type = 0x80; + + /* convert time to what the card wants */ + ips_fix_ffdc_time(ha, scb, ha->last_ffdc); + + /* issue command */ + ips_send_wait(ha, scb, ips_cmd_timeout, intr); +} + +/****************************************************************************/ +/* */ +/* Routine Name: ips_ffdc_time */ +/* */ +/* Routine Description: */ +/* */ +/* FFDC: write time info */ +/* */ +/****************************************************************************/ +static void +ips_ffdc_time(ips_ha_t *ha, int intr) { + ips_scb_t *scb; + + DBG("ips_ffdc_time"); + +#if IPS_DEBUG >= 1 + printk(KERN_NOTICE "(%s%d) Sending time update.\n", + ips_name, ha->host_num); +#endif + + scb = &ha->scbs[ha->max_cmds-1]; + + ips_init_scb(ha, scb); + + scb->timeout = ips_cmd_timeout; + scb->cdb[0] = IPS_CMD_FFDC; + scb->cmd.ffdc.op_code = IPS_CMD_FFDC; + scb->cmd.ffdc.command_id = IPS_COMMAND_ID(ha, scb); + scb->cmd.ffdc.reset_count = 0; + scb->cmd.ffdc.reset_type = 0x80; + + /* convert time to what the card wants */ + ips_fix_ffdc_time(ha, scb, ha->last_ffdc); + + /* issue command */ + ips_send_wait(ha, scb, ips_cmd_timeout, intr); +} + +/****************************************************************************/ +/* */ +/* Routine Name: ips_fix_ffdc_time */ +/* */ +/* Routine Description: */ +/* Adjust time_t to what the card wants */ +/* */ +/****************************************************************************/ +static void +ips_fix_ffdc_time(ips_ha_t *ha, ips_scb_t *scb, time_t current_time) { + long days; + long rem; + int i; + int year; + int yleap; + int year_lengths[2] = { IPS_DAYS_NORMAL_YEAR, IPS_DAYS_LEAP_YEAR }; + int month_lengths[12][2] = { {31, 31}, + {28, 29}, + {31, 31}, + {30, 30}, + {31, 31}, + {30, 30}, + {31, 31}, + {31, 31}, + {30, 30}, + {31, 31}, + {30, 30}, + {31, 31} }; + + days = current_time / IPS_SECS_DAY; + rem = current_time % IPS_SECS_DAY; + + scb->cmd.ffdc.hour = (rem / IPS_SECS_HOUR); + rem = rem % IPS_SECS_HOUR; + scb->cmd.ffdc.minute = (rem / IPS_SECS_MIN); + scb->cmd.ffdc.second = (rem % IPS_SECS_MIN); + + year = IPS_EPOCH_YEAR; + while (days < 0 || days >= year_lengths[yleap = IPS_IS_LEAP_YEAR(year)]) { + int newy; + + newy = year + (days / IPS_DAYS_NORMAL_YEAR); + if (days < 0) + --newy; + days -= (newy - year) * IPS_DAYS_NORMAL_YEAR + + IPS_NUM_LEAP_YEARS_THROUGH(newy - 1) - + IPS_NUM_LEAP_YEARS_THROUGH(year - 1); + year = newy; + } + + scb->cmd.ffdc.yearH = year / 100; + scb->cmd.ffdc.yearL = year % 100; + + for (i = 0; days >= month_lengths[i][yleap]; ++i) + days -= month_lengths[i][yleap]; + + scb->cmd.ffdc.month = i + 1; + scb->cmd.ffdc.day = days + 1; +} + +/**************************************************************************** + * BIOS Flash Routines * + ****************************************************************************/ + +/****************************************************************************/ +/* */ +/* Routine Name: ips_erase_bios */ +/* */ +/* Routine Description: */ +/* Erase the BIOS on the adapter */ +/* */ +/****************************************************************************/ +static int +ips_erase_bios(ips_ha_t *ha) { + int timeout; + u8 status; + + /* Clear the status register */ + outl(0, ha->io_addr + IPS_REG_FLAP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + outb(0x50, ha->io_addr + IPS_REG_FLDP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + /* Erase Setup */ + outb(0x20, ha->io_addr + IPS_REG_FLDP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + /* Erase Confirm */ + outb(0xD0, ha->io_addr + IPS_REG_FLDP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + /* Erase Status */ + outb(0x70, ha->io_addr + IPS_REG_FLDP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + timeout = 80000; /* 80 seconds */ + + while (timeout > 0) { + if (ha->revision_id == IPS_REVID_TROMBONE64) { + outl(0, ha->io_addr + IPS_REG_FLAP); + UDELAY(5); /* 5 us */ + } + + status = inb(ha->io_addr + IPS_REG_FLDP); + + if (status & 0x80) + break; + + MDELAY(1); + timeout--; + } + + /* check for timeout */ + if (timeout <= 0) { + /* timeout */ + + /* try to suspend the erase */ + outb(0xB0, ha->io_addr + IPS_REG_FLDP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + /* wait for 10 seconds */ + timeout = 10000; + while (timeout > 0) { + if (ha->revision_id == IPS_REVID_TROMBONE64) { + outl(0, ha->io_addr + IPS_REG_FLAP); + UDELAY(5); /* 5 us */ + } + + status = inb(ha->io_addr + IPS_REG_FLDP); + + if (status & 0xC0) + break; + + MDELAY(1); + timeout--; + } + + return (1); + } + + /* check for valid VPP */ + if (status & 0x08) + /* VPP failure */ + return (1); + + /* check for succesful flash */ + if (status & 0x30) + /* sequence error */ + return (1); + + /* Otherwise, we were successful */ + /* clear status */ + outb(0x50, ha->io_addr + IPS_REG_FLDP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + /* enable reads */ + outb(0xFF, ha->io_addr + IPS_REG_FLDP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + return (0); +} + +/****************************************************************************/ +/* */ +/* Routine Name: ips_program_bios */ +/* */ +/* Routine Description: */ +/* Program the BIOS on the adapter */ +/* */ +/****************************************************************************/ +static int +ips_program_bios(ips_ha_t *ha, char *buffer, int buffersize) { + int i; + int timeout; + u8 status; + + for (i = 0; i < buffersize; i++) { + /* write a byte */ + outl(i, ha->io_addr + IPS_REG_FLAP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + outb(0x40, ha->io_addr + IPS_REG_FLDP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + outb(buffer[i], ha->io_addr + IPS_REG_FLDP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + /* wait up to one second */ + timeout = 1000; + while (timeout > 0) { + if (ha->revision_id == IPS_REVID_TROMBONE64) { + outl(0, ha->io_addr + IPS_REG_FLAP); + UDELAY(5); /* 5 us */ + } + + status = inb(ha->io_addr + IPS_REG_FLDP); + + if (status & 0x80) + break; + + MDELAY(1); + timeout--; + } + + if (timeout == 0) { + /* timeout error */ + outl(0, ha->io_addr + IPS_REG_FLAP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + outb(0xFF, ha->io_addr + IPS_REG_FLDP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + return (1); + } + + /* check the status */ + if (status & 0x18) { + /* programming error */ + outl(0, ha->io_addr + IPS_REG_FLAP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + outb(0xFF, ha->io_addr + IPS_REG_FLDP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + return (1); + } + } /* end for */ + + /* Enable reading */ + outl(0, ha->io_addr + IPS_REG_FLAP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + outb(0xFF, ha->io_addr + IPS_REG_FLDP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + return (0); +} + +/****************************************************************************/ +/* */ +/* Routine Name: ips_verify_bios */ +/* */ +/* Routine Description: */ +/* Verify the BIOS on the adapter */ +/* */ +/****************************************************************************/ +static int +ips_verify_bios(ips_ha_t *ha, char *buffer, int buffersize) { + u8 checksum; + int i; + + /* test 1st byte */ + outl(0, ha->io_addr + IPS_REG_FLAP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + if (inb(ha->io_addr + IPS_REG_FLDP) != 0x55) + return (1); + + outl(1, ha->io_addr + IPS_REG_FLAP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + if (inb(ha->io_addr + IPS_REG_FLDP) != 0xAA) + return (1); + + checksum = 0xff; + for (i = 2; i < buffersize; i++) { + + outl(i, ha->io_addr + IPS_REG_FLAP); + if (ha->revision_id == IPS_REVID_TROMBONE64) + UDELAY(5); /* 5 us */ + + checksum = (u8) checksum + inb(ha->io_addr + IPS_REG_FLDP); + } + + if (checksum != 0) + /* failure */ + return (1); + else + /* success */ + return (0); } #if defined (MODULE) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/scsi/ips.h linux/drivers/scsi/ips.h --- v2.4.0-test5/linux/drivers/scsi/ips.h Mon Dec 20 18:48:22 1999 +++ linux/drivers/scsi/ips.h Wed Aug 9 18:59:41 2000 @@ -47,7 +47,6 @@ #ifndef _IPS_H_ #define _IPS_H_ - #include #include #include @@ -67,209 +66,276 @@ * Some handy macros */ #ifndef LinuxVersionCode - #define LinuxVersionCode(x,y,z) (((x)<<16)+((y)<<8)+(z)) + #define LinuxVersionCode(x,y,z) (((x)<<16)+((y)<<8)+(z)) #endif - #define HA(x) ((ips_ha_t *) x->hostdata) + #define IPS_HA(x) ((ips_ha_t *) x->hostdata) #define IPS_COMMAND_ID(ha, scb) (int) (scb - ha->scbs) - #define VIRT_TO_BUS(x) (unsigned int)virt_to_bus((void *) x) + + #ifndef VIRT_TO_BUS + #define VIRT_TO_BUS(x) (unsigned int)virt_to_bus((void *) x) + #endif - #define UDELAY udelay - #define MDELAY mdelay + #ifndef UDELAY + #define UDELAY udelay + #endif + + #ifndef MDELAY + #define MDELAY mdelay + #endif - #define verify_area_20(t,a,sz) (0) /* success */ - #define PUT_USER put_user - #define __PUT_USER __put_user - #define PUT_USER_RET put_user_ret - #define GET_USER get_user - #define __GET_USER __get_user - #define GET_USER_RET get_user_ret + #ifndef verify_area_20 + #define verify_area_20(t,a,sz) (0) /* success */ + #endif + + #ifndef PUT_USER + #define PUT_USER put_user + #endif + + #ifndef __PUT_USER + #define __PUT_USER __put_user + #endif + + #ifndef PUT_USER_RET + #define PUT_USER_RET put_user_ret + #endif + + #ifndef GET_USER + #define GET_USER get_user + #endif + + #ifndef __GET_USER + #define __GET_USER __get_user + #endif + + #ifndef GET_USER_RET + #define GET_USER_RET get_user_ret + #endif -/* - * Adapter address map equates - */ - #define HISR 0x08 /* Host Interrupt Status Reg */ - #define CCSAR 0x10 /* Cmd Channel System Addr Reg */ - #define CCCR 0x14 /* Cmd Channel Control Reg */ - #define SQHR 0x20 /* Status Q Head Reg */ - #define SQTR 0x24 /* Status Q Tail Reg */ - #define SQER 0x28 /* Status Q End Reg */ - #define SQSR 0x2C /* Status Q Start Reg */ - #define SCPR 0x05 /* Subsystem control port reg */ - #define ISPR 0x06 /* interrupt status port reg */ - #define CBSP 0x07 /* CBSP register */ + /* + * Lock macros + */ + #define IPS_SCB_LOCK(cpu_flags) spin_lock_irqsave(&ha->scb_lock, cpu_flags) + #define IPS_SCB_UNLOCK(cpu_flags) spin_unlock_irqrestore(&ha->scb_lock, cpu_flags) + #define IPS_QUEUE_LOCK(queue) spin_lock_irqsave(&(queue)->lock, (queue)->cpu_flags) + #define IPS_QUEUE_UNLOCK(queue) spin_unlock_irqrestore(&(queue)->lock, (queue)->cpu_flags) + #define IPS_HA_LOCK(cpu_flags) spin_lock_irqsave(&ha->ips_lock, cpu_flags) + #define IPS_HA_UNLOCK(cpu_flags) spin_unlock_irqrestore(&ha->ips_lock, cpu_flags) -/* - * Adapter register bit equates - */ - #define GHI 0x04 /* HISR General Host Interrupt */ - #define SQO 0x02 /* HISR Status Q Overflow */ - #define SCE 0x01 /* HISR Status Channel Enqueue */ - #define SEMAPHORE 0x08 /* CCCR Semaphore Bit */ - #define ILE 0x10 /* CCCR ILE Bit */ - #define START_COMMAND 0x101A /* CCCR Start Command Channel */ - #define START_STOP_BIT 0x0002 /* CCCR Start/Stop Bit */ - #define RST 0x80 /* SCPR Reset Bit */ - #define EBM 0x02 /* SCPR Enable Bus Master */ - #define EI 0x80 /* HISR Enable Interrupts */ - #define OP 0x01 /* OP bit in CBSP */ + /* + * Adapter address map equates + */ + #define IPS_REG_HISR 0x08 /* Host Interrupt Status Reg */ + #define IPS_REG_CCSAR 0x10 /* Cmd Channel System Addr Reg */ + #define IPS_REG_CCCR 0x14 /* Cmd Channel Control Reg */ + #define IPS_REG_SQHR 0x20 /* Status Q Head Reg */ + #define IPS_REG_SQTR 0x24 /* Status Q Tail Reg */ + #define IPS_REG_SQER 0x28 /* Status Q End Reg */ + #define IPS_REG_SQSR 0x2C /* Status Q Start Reg */ + #define IPS_REG_SCPR 0x05 /* Subsystem control port reg */ + #define IPS_REG_ISPR 0x06 /* interrupt status port reg */ + #define IPS_REG_CBSP 0x07 /* CBSP register */ + #define IPS_REG_FLAP 0x18 /* Flash address port */ + #define IPS_REG_FLDP 0x1C /* Flash data port */ -/* - * Adapter Command ID Equates - */ - #define GET_LOGICAL_DRIVE_INFO 0x19 - #define GET_SUBSYS_PARAM 0x40 - #define READ_NVRAM_CONFIGURATION 0x38 - #define RW_NVRAM_PAGE 0xBC - #define IPS_READ 0x02 - #define IPS_WRITE 0x03 - #define ENQUIRY 0x05 - #define FLUSH_CACHE 0x0A - #define NORM_STATE 0x00 - #define READ_SCATTER_GATHER 0x82 - #define WRITE_SCATTER_GATHER 0x83 - #define DIRECT_CDB 0x04 - #define DIRECT_CDB_SCATTER_GATHER 0x84 - #define CONFIG_SYNC 0x58 - #define POCL 0x30 - #define GET_ERASE_ERROR_TABLE 0x17 - #define RESET_CHANNEL 0x1A - #define CSL 0xFF - #define ADAPT_RESET 0xFF + /* + * Adapter register bit equates + */ + #define IPS_BIT_GHI 0x04 /* HISR General Host Interrupt */ + #define IPS_BIT_SQO 0x02 /* HISR Status Q Overflow */ + #define IPS_BIT_SCE 0x01 /* HISR Status Channel Enqueue */ + #define IPS_BIT_SEM 0x08 /* CCCR Semaphore Bit */ + #define IPS_BIT_ILE 0x10 /* CCCR ILE Bit */ + #define IPS_BIT_START_CMD 0x101A /* CCCR Start Command Channel */ + #define IPS_BIT_START_STOP 0x0002 /* CCCR Start/Stop Bit */ + #define IPS_BIT_RST 0x80 /* SCPR Reset Bit */ + #define IPS_BIT_EBM 0x02 /* SCPR Enable Bus Master */ + #define IPS_BIT_EI 0x80 /* HISR Enable Interrupts */ + #define IPS_BIT_OP 0x01 /* OP bit in CBSP */ -/* - * Adapter Equates - */ + /* + * Adapter Command ID Equates + */ + #define IPS_CMD_GET_LD_INFO 0x19 + #define IPS_CMD_GET_SUBSYS 0x40 + #define IPS_CMD_READ_CONF 0x38 + #define IPS_CMD_RW_NVRAM_PAGE 0xBC + #define IPS_CMD_READ 0x02 + #define IPS_CMD_WRITE 0x03 + #define IPS_CMD_FFDC 0xD7 + #define IPS_CMD_ENQUIRY 0x05 + #define IPS_CMD_FLUSH 0x0A + #define IPS_CMD_READ_SG 0x82 + #define IPS_CMD_WRITE_SG 0x83 + #define IPS_CMD_DCDB 0x04 + #define IPS_CMD_DCDB_SG 0x84 + #define IPS_CMD_CONFIG_SYNC 0x58 + #define IPS_CMD_ERROR_TABLE 0x17 + + /* + * Adapter Equates + */ + #define IPS_CSL 0xFF + #define IPS_POCL 0x30 + #define IPS_NORM_STATE 0x00 #define IPS_MAX_ADAPTERS 16 #define IPS_MAX_IOCTL 1 #define IPS_MAX_IOCTL_QUEUE 8 #define IPS_MAX_QUEUE 128 #define IPS_BLKSIZE 512 - #define MAX_SG_ELEMENTS 17 - #define MAX_LOGICAL_DRIVES 8 - #define MAX_CHANNELS 3 - #define MAX_TARGETS 15 - #define MAX_CHUNKS 16 - #define MAX_CMDS 128 + #define IPS_MAX_SG 17 + #define IPS_MAX_LD 8 + #define IPS_MAX_CHANNELS 4 + #define IPS_MAX_TARGETS 15 + #define IPS_MAX_CHUNKS 16 + #define IPS_MAX_CMDS 128 #define IPS_MAX_XFER 0x10000 - #define COMP_MODE_HEADS 128 - #define COMP_MODE_SECTORS 32 - #define NORM_MODE_HEADS 254 - #define NORM_MODE_SECTORS 63 - #define NVRAM_PAGE5_SIGNATURE 0xFFDDBB99 - #define MAX_POST_BYTES 0x02 - #define MAX_CONFIG_BYTES 0x02 - #define GOOD_POST_BASIC_STATUS 0x80 - #define SEMAPHORE_TIMEOUT 2000 - #define IPS_INTR_OFF 0 - #define IPS_INTR_ON 1 + #define IPS_NVRAM_P5_SIG 0xFFDDBB99 + #define IPS_MAX_POST_BYTES 0x02 + #define IPS_MAX_CONFIG_BYTES 0x02 + #define IPS_GOOD_POST_STATUS 0x80 + #define IPS_SEM_TIMEOUT 2000 + #define IPS_IOCTL_COMMAND 0x0D + #define IPS_IOCTL_NEW_COMMAND 0x81 + #define IPS_INTR_ON 0 + #define IPS_INTR_IORL 1 + #define IPS_INTR_HAL 2 #define IPS_ADAPTER_ID 0xF #define IPS_VENDORID 0x1014 #define IPS_DEVICEID 0x002E - #define TIMEOUT_10 0x10 - #define TIMEOUT_60 0x20 - #define TIMEOUT_20M 0x30 - #define STATUS_SIZE 4 - #define STATUS_Q_SIZE (MAX_CMDS+1) * STATUS_SIZE - #define ONE_MSEC 1 - #define ONE_SEC 1000 + #define IPS_IOCTL_SIZE 8192 + #define IPS_STATUS_SIZE 4 + #define IPS_STATUS_Q_SIZE (IPS_MAX_CMDS+1) * IPS_STATUS_SIZE + #define IPS_ONE_MSEC 1 + #define IPS_ONE_SEC 1000 + + /* + * Geometry Settings + */ + #define IPS_COMP_HEADS 128 + #define IPS_COMP_SECTORS 32 + #define IPS_NORM_HEADS 254 + #define IPS_NORM_SECTORS 63 -/* - * Adapter Basic Status Codes - */ - #define BASIC_STATUS_MASK 0xFF - #define GSC_STATUS_MASK 0x0F - #define SSUCCESS 0x00 - #define RECOVERED_ERROR 0x01 - #define IPS_CHECK_CONDITION 0x02 - #define INVAL_OPCO 0x03 - #define INVAL_CMD_BLK 0x04 - #define INVAL_PARM_BLK 0x05 + /* + * Adapter Basic Status Codes + */ + #define IPS_BASIC_STATUS_MASK 0xFF + #define IPS_GSC_STATUS_MASK 0x0F + #define IPS_CMD_SUCCESS 0x00 + #define IPS_CMD_RECOVERED_ERROR 0x01 + #define IPS_INVAL_OPCO 0x03 + #define IPS_INVAL_CMD_BLK 0x04 + #define IPS_INVAL_PARM_BLK 0x05 #define IPS_BUSY 0x08 - #define ADAPT_HARDWARE_ERROR 0x09 - #define ADAPT_FIRMWARE_ERROR 0x0A - #define CMD_CMPLT_WERROR 0x0C - #define LOG_DRV_ERROR 0x0D - #define CMD_TIMEOUT 0x0E - #define PHYS_DRV_ERROR 0x0F + #define IPS_CMD_CMPLT_WERROR 0x0C + #define IPS_LD_ERROR 0x0D + #define IPS_CMD_TIMEOUT 0x0E + #define IPS_PHYS_DRV_ERROR 0x0F -/* - * Adapter Extended Status Equates - */ - #define SELECTION_TIMEOUT 0xF0 - #define DATA_OVER_UNDER_RUN 0xF2 - #define EXT_HOST_RESET 0xF7 - #define EXT_DEVICE_RESET 0xF8 - #define EXT_RECOVERY 0xFC - #define EXT_CHECK_CONDITION 0xFF + /* + * Adapter Extended Status Equates + */ + #define IPS_ERR_SEL_TO 0xF0 + #define IPS_ERR_OU_RUN 0xF2 + #define IPS_ERR_HOST_RESET 0xF7 + #define IPS_ERR_DEV_RESET 0xF8 + #define IPS_ERR_RECOVERY 0xFC + #define IPS_ERR_CKCOND 0xFF -/* - * Operating System Defines - */ - #define OS_WINDOWS_NT 0x01 - #define OS_NETWARE 0x02 - #define OS_OPENSERVER 0x03 - #define OS_UNIXWARE 0x04 - #define OS_SOLARIS 0x05 - #define OS_OS2 0x06 - #define OS_LINUX 0x07 - #define OS_FREEBSD 0x08 + /* + * Operating System Defines + */ + #define IPS_OS_WINDOWS_NT 0x01 + #define IPS_OS_NETWARE 0x02 + #define IPS_OS_OPENSERVER 0x03 + #define IPS_OS_UNIXWARE 0x04 + #define IPS_OS_SOLARIS 0x05 + #define IPS_OS_OS2 0x06 + #define IPS_OS_LINUX 0x07 + #define IPS_OS_FREEBSD 0x08 -/* - * Adapter Command/Status Packet Definitions - */ + /* + * Adapter Revision ID's + */ + #define IPS_REVID_SERVERAID 0x02 + #define IPS_REVID_NAVAJO 0x03 + #define IPS_REVID_SERVERAID2 0x04 + #define IPS_REVID_CLARINETP1 0x05 + #define IPS_REVID_CLARINETP2 0x07 + #define IPS_REVID_CLARINETP3 0x0D + #define IPS_REVID_TROMBONE32 0x0F + #define IPS_REVID_TROMBONE64 0x10 + + /* + * Adapter Command/Status Packet Definitions + */ #define IPS_SUCCESS 0x01 /* Successfully completed */ #define IPS_SUCCESS_IMM 0x02 /* Success - Immediately */ #define IPS_FAILURE 0x04 /* Completed with Error */ -/* - * Logical Drive Equates - */ - #define OFF_LINE 0x02 - #define OKAY 0x03 - #define FREE 0x00 - #define SYS 0x06 - #define CRS 0x24 + /* + * Logical Drive Equates + */ + #define IPS_LD_OFFLINE 0x02 + #define IPS_LD_OKAY 0x03 + #define IPS_LD_FREE 0x00 + #define IPS_LD_SYS 0x06 + #define IPS_LD_CRS 0x24 -/* - * DCDB Table Equates - */ - #define NO_DISCONNECT 0x00 - #define DISCONNECT_ALLOWED 0x80 - #define NO_AUTO_REQUEST_SENSE 0x40 - #define IPS_DATA_NONE 0x00 - #define IPS_DATA_UNK 0x00 + /* + * DCDB Table Equates + */ + #define IPS_NO_DISCONNECT 0x00 + #define IPS_DISCONNECT_ALLOWED 0x80 + #define IPS_NO_AUTO_REQSEN 0x40 + #define IPS_DATA_NONE 0x00 + #define IPS_DATA_UNK 0x00 #define IPS_DATA_IN 0x01 #define IPS_DATA_OUT 0x02 - #define TRANSFER_64K 0x08 - #define NOTIMEOUT 0x00 - #define TIMEOUT10 0x10 - #define TIMEOUT60 0x20 - #define TIMEOUT20M 0x30 + #define IPS_TRANSFER64K 0x08 + #define IPS_NOTIMEOUT 0x00 + #define IPS_TIMEOUT10 0x10 + #define IPS_TIMEOUT60 0x20 + #define IPS_TIMEOUT20M 0x30 -/* - * Host adapter Flags (bit numbers) - */ + /* + * Host adapter Flags (bit numbers) + */ #define IPS_IN_INTR 0 #define IPS_IN_ABORT 1 #define IPS_IN_RESET 2 -/* - * SCB Flags - */ - #define SCB_ACTIVE 0x00001 - #define SCB_WAITING 0x00002 + /* + * SCB Flags + */ + #define IPS_SCB_ACTIVE 0x00001 + #define IPS_SCB_WAITING 0x00002 -/* - * Passthru stuff - */ - #define COPPUSRCMD (('C'<<8) | 65) + /* + * Passthru stuff + */ + #define IPS_COPPUSRCMD (('C'<<8) | 65) + #define IPS_COPPIOCCMD (('C'<<8) | 66) #define IPS_NUMCTRLS (('C'<<8) | 68) #define IPS_CTRLINFO (('C'<<8) | 69) + #define IPS_FLASHBIOS (('C'<<8) | 70) -/* - * Scsi_Host Template - */ + /* time oriented stuff */ + #define IPS_IS_LEAP_YEAR(y) (((y % 4 == 0) && ((y % 100 != 0) || (y % 400 == 0))) ? 1 : 0) + #define IPS_NUM_LEAP_YEARS_THROUGH(y) ((y) / 4 - (y) / 100 + (y) / 400) + + #define IPS_SECS_MIN 60 + #define IPS_SECS_HOUR 3600 + #define IPS_SECS_8HOURS 28800 + #define IPS_SECS_DAY 86400 + #define IPS_DAYS_NORMAL_YEAR 365 + #define IPS_DAYS_LEAP_YEAR 366 + #define IPS_EPOCH_YEAR 1970 + + /* + * Scsi_Host Template + */ #define IPS { \ next : NULL, \ module : NULL, \ @@ -291,7 +357,7 @@ bios_param : ips_biosparam, \ can_queue : 0, \ this_id: -1, \ - sg_tablesize : MAX_SG_ELEMENTS, \ + sg_tablesize : IPS_MAX_SG, \ cmd_per_lun: 16, \ present : 0, \ unchecked_isa_dma : 0, \ @@ -313,7 +379,7 @@ u16 reserved; u32 ccsar; u32 cccr; -} BASIC_IO_CMD, *PBASIC_IO_CMD; +} IPS_IO_CMD, *PIPS_IO_CMD; typedef struct { u8 op_code; @@ -324,7 +390,7 @@ u32 reserved3; u32 ccsar; u32 cccr; -} LOGICAL_INFO, *PLOGICAL_INFO; +} IPS_LD_CMD, *PIPS_LD_CMD; typedef struct { u8 op_code; @@ -334,7 +400,7 @@ u32 reserved3; u32 buffer_addr; u32 reserved4; -} IOCTL_INFO, *PIOCTL_INFO; +} IPS_IOCTL_CMD, *PIPS_IOCTL_CMD; typedef struct { u8 op_code; @@ -345,7 +411,7 @@ u32 reserved3; u32 ccsar; u32 cccr; -} DCDB_CMD, *PDCDB_CMD; +} IPS_DCDB_CMD, *PIPS_DCDB_CMD; typedef struct { u8 op_code; @@ -357,7 +423,7 @@ u32 reserved3; u32 ccsar; u32 cccr; -} CONFIG_SYNC_CMD, *PCONFIG_SYNC_CMD; +} IPS_CS_CMD, *PIPS_CS_CMD; typedef struct { u8 op_code; @@ -369,7 +435,7 @@ u32 reserved3; u32 ccsar; u32 cccr; -} UNLOCK_STRIPE_CMD, *PUNLOCK_STRIPE_CMD; +} IPS_US_CMD, *PIPS_US_CMD; typedef struct { u8 op_code; @@ -381,7 +447,7 @@ u32 reserved4; u32 ccsar; u32 cccr; -} FLUSH_CACHE_CMD, *PFLUSH_CACHE_CMD; +} IPS_FC_CMD, *PIPS_FC_CMD; typedef struct { u8 op_code; @@ -393,7 +459,7 @@ u32 reserved3; u32 ccsar; u32 cccr; -} STATUS_CMD, *PSTATUS_CMD; +} IPS_STATUS_CMD, *PIPS_STATUS_CMD; typedef struct { u8 op_code; @@ -405,19 +471,36 @@ u32 reserved2; u32 ccsar; u32 cccr; -} NVRAM_CMD, *PNVRAM_CMD; +} IPS_NVRAM_CMD, *PIPS_NVRAM_CMD; + +typedef struct { + u8 op_code; + u8 command_id; + u8 reset_count; + u8 reset_type; + u8 second; + u8 minute; + u8 hour; + u8 day; + u8 reserved1[4]; + u8 month; + u8 yearH; + u8 yearL; + u8 reserved2; +} IPS_FFDC_CMD, *PIPS_FFDC_CMD; typedef union { - BASIC_IO_CMD basic_io; - LOGICAL_INFO logical_info; - IOCTL_INFO ioctl_info; - DCDB_CMD dcdb; - CONFIG_SYNC_CMD config_sync; - UNLOCK_STRIPE_CMD unlock_stripe; - FLUSH_CACHE_CMD flush_cache; - STATUS_CMD status; - NVRAM_CMD nvram; -} HOST_COMMAND, *PHOST_COMMAND; + IPS_IO_CMD basic_io; + IPS_LD_CMD logical_info; + IPS_IOCTL_CMD ioctl_info; + IPS_DCDB_CMD dcdb; + IPS_CS_CMD config_sync; + IPS_US_CMD unlock_stripe; + IPS_FC_CMD flush_cache; + IPS_STATUS_CMD status; + IPS_NVRAM_CMD nvram; + IPS_FFDC_CMD ffdc; +} IPS_HOST_COMMAND, *PIPS_HOST_COMMAND; typedef struct { u8 logical_id; @@ -425,25 +508,13 @@ u8 raid_level; u8 state; u32 sector_count; -} DRIVE_INFO, *PDRIVE_INFO; +} IPS_DRIVE_INFO, *PIPS_DRIVE_INFO; typedef struct { - u8 no_of_log_drive; - u8 reserved[3]; - DRIVE_INFO drive_info[MAX_LOGICAL_DRIVES]; -} LOGICAL_DRIVE_INFO, *PLOGICAL_DRIVE_INFO; - -typedef struct { - u8 ha_num; - u8 bus_num; - u8 id; - u8 device_type; - u32 data_len; - u32 data_ptr; - u8 scsi_cdb[12]; - u32 data_counter; - u32 block_size; -} NON_DISK_DEVICE_INFO, *PNON_DISK_DEVICE_INFO; + u8 no_of_log_drive; + u8 reserved[3]; + IPS_DRIVE_INFO drive_info[IPS_MAX_LD]; +} IPS_LD_INFO, *PIPS_LD_INFO; typedef struct { u8 device_address; @@ -458,24 +529,24 @@ u8 sense_info[64]; u8 scsi_status; u8 reserved2[3]; -} DCDB_TABLE, *PDCDB_TABLE; +} IPS_DCDB_TABLE, *PIPS_DCDB_TABLE; typedef struct { volatile u8 reserved; volatile u8 command_id; volatile u8 basic_status; volatile u8 extended_status; -} STATUS, *PSTATUS; +} IPS_STATUS, *PIPS_STATUS; typedef struct { - STATUS status[MAX_CMDS + 1]; - volatile PSTATUS p_status_start; - volatile PSTATUS p_status_end; - volatile PSTATUS p_status_tail; + IPS_STATUS status[IPS_MAX_CMDS + 1]; + volatile PIPS_STATUS p_status_start; + volatile PIPS_STATUS p_status_end; + volatile PIPS_STATUS p_status_tail; volatile u32 hw_status_start; volatile u32 hw_status_tail; - LOGICAL_DRIVE_INFO logical_drive_info; -} ADAPTER_AREA, *PADAPTER_AREA; + IPS_LD_INFO logical_drive_info; +} IPS_ADAPTER, *PIPS_ADAPTER; typedef struct { u8 ucLogDriveCount; @@ -488,7 +559,7 @@ u8 ucNVramDevChgCnt; u8 CodeBlkVersion[8]; u8 BootBlkVersion[8]; - u32 ulDriveSize[MAX_LOGICAL_DRIVES]; + u32 ulDriveSize[IPS_MAX_LD]; u8 ucConcurrentCmdCount; u8 ucMaxPhysicalDevices; u16 usFlashRepgmCount; @@ -499,8 +570,8 @@ u16 usConfigUpdateCount; u8 ucBlkFlag; u8 reserved; - u16 usAddrDeadDisk[MAX_CHANNELS * MAX_TARGETS]; -} ENQCMD, *PENQCMD; + u16 usAddrDeadDisk[IPS_MAX_CHANNELS * IPS_MAX_TARGETS]; +} IPS_ENQ, *PIPS_ENQ; typedef struct { u8 ucInitiator; @@ -509,7 +580,7 @@ u8 ucState; u32 ulBlockCount; u8 ucDeviceId[28]; -} DEVSTATE, *PDEVSTATE; +} IPS_DEVSTATE, *PIPS_DEVSTATE; typedef struct { u8 ucChn; @@ -517,7 +588,7 @@ u16 ucReserved; u32 ulStartSect; u32 ulNoOfSects; -} CHUNK, *PCHUNK; +} IPS_CHUNK, *PIPS_CHUNK; typedef struct { u16 ucUserField; @@ -528,8 +599,8 @@ u8 ucParams; u8 ucReserved; u32 ulLogDrvSize; - CHUNK chunk[MAX_CHUNKS]; -} LOGICAL_DRIVE, *PLOGICAL_DRIVE; + IPS_CHUNK chunk[IPS_MAX_CHUNKS]; +} IPS_LD, *PIPS_LD; typedef struct { u8 board_disc[8]; @@ -539,7 +610,7 @@ u8 ucCompression; u8 ucNvramType; u32 ulNvramSize; -} HARDWARE_DISC, *PHARDWARE_DISC; +} IPS_HARDWARE, *PIPS_HARDWARE; typedef struct { u8 ucLogDriveCount; @@ -563,12 +634,12 @@ u16 user_field; u8 ucRebuildRate; u8 ucReserve; - HARDWARE_DISC hardware_disc; - LOGICAL_DRIVE logical_drive[MAX_LOGICAL_DRIVES]; - DEVSTATE dev[MAX_CHANNELS][MAX_TARGETS+1]; + IPS_HARDWARE hardware_disc; + IPS_LD logical_drive[IPS_MAX_LD]; + IPS_DEVSTATE dev[IPS_MAX_CHANNELS][IPS_MAX_TARGETS+1]; u8 reserved[512]; -} CONFCMD, *PCONFCMD; +} IPS_CONF, *PIPS_CONF; typedef struct { u32 signature; @@ -583,11 +654,11 @@ u8 driver_high[4]; u8 driver_low[4]; u8 reserved4[100]; -} NVRAM_PAGE5, *PNVRAM_PAGE5; +} IPS_NVRAM_P5, *PIPS_NVRAM_P5; -typedef struct _SUBSYS_PARAM { +typedef struct _IPS_SUBSYS { u32 param[128]; -} SUBSYS_PARAM, *PSUBSYS_PARAM; +} IPS_SUBSYS, *PIPS_SUBSYS; /* * Inquiry Data Format @@ -614,7 +685,7 @@ u8 ProductRevisionLevel[4]; u8 VendorSpecific[20]; u8 Reserved3[40]; -} IPS_INQUIRYDATA, *IPS_PINQUIRYDATA; +} IPS_INQ_DATA, *PIPS_INQ_DATA; /* * Read Capacity Data Format @@ -622,7 +693,7 @@ typedef struct { u32 lba; u32 len; -} CAPACITY_T; +} IPS_CAPACITY; /* * Sense Data Format @@ -646,7 +717,7 @@ u32 pg_rmb:1; /* Removeable */ u32 pg_hsec:1; /* Hard sector formatting */ u32 pg_ssec:1; /* Soft sector formatting */ -} DADF_T; +} IPS_DADF; typedef struct { u8 pg_pc:6; /* Page Code */ @@ -662,9 +733,9 @@ u32 pg_landu:16; /* Landing zone cylinder (upper) */ u32 pg_landl:8; /* Landing zone cylinder (lower) */ u32 pg_res2:24; /* Reserved */ -} RDDG_T; +} IPS_RDDG; -struct blk_desc { +struct ips_blk_desc { u8 bd_dencode; u8 bd_nblks1; u8 bd_nblks2; @@ -681,15 +752,15 @@ u8 plh_res:7; /* Reserved */ u8 plh_wp:1; /* Write protect */ u8 plh_bdl; /* Block descriptor length */ -} SENSE_PLH_T; +} ips_sense_plh_t; typedef struct { - SENSE_PLH_T plh; - struct blk_desc blk_desc; + ips_sense_plh_t plh; + struct ips_blk_desc blk_desc; union { - DADF_T pg3; - RDDG_T pg4; + IPS_DADF pg3; + IPS_RDDG pg4; } pdata; } ips_mdata_t; @@ -699,14 +770,14 @@ typedef struct ips_sglist { u32 address; u32 length; -} SG_LIST, *PSG_LIST; +} IPS_SG_LIST, *PIPS_SG_LIST; -typedef struct _INFOSTR { +typedef struct _IPS_INFOSTR { char *buffer; int length; int offset; int pos; -} INFOSTR; +} IPS_INFOSTR; /* * Status Info @@ -722,7 +793,9 @@ typedef struct ips_scb_queue { struct ips_scb *head; struct ips_scb *tail; - unsigned int count; + u32 count; + u32 cpu_flags; + spinlock_t lock; } ips_scb_queue_t; /* @@ -731,12 +804,28 @@ typedef struct ips_wait_queue { Scsi_Cmnd *head; Scsi_Cmnd *tail; - unsigned int count; + u32 count; + u32 cpu_flags; + spinlock_t lock; } ips_wait_queue_t; +typedef struct ips_copp_wait_item { + Scsi_Cmnd *scsi_cmd; + struct semaphore *sem; + struct ips_copp_wait_item *next; +} ips_copp_wait_item_t; + +typedef struct ips_copp_queue { + struct ips_copp_wait_item *head; + struct ips_copp_wait_item *tail; + u32 count; + u32 cpu_flags; + spinlock_t lock; +} ips_copp_queue_t; + typedef struct ips_ha { - u8 ha_id[MAX_CHANNELS+1]; - u32 dcdb_active[MAX_CHANNELS]; + u8 ha_id[IPS_MAX_CHANNELS+1]; + u32 dcdb_active[IPS_MAX_CHANNELS]; u32 io_addr; /* Base I/O address */ u8 irq; /* IRQ for adapter */ u8 ntargets; /* Number of targets */ @@ -751,35 +840,39 @@ struct ips_scb *scbs; /* Array of all CCBS */ struct ips_scb *scb_freelist; /* SCB free list */ ips_wait_queue_t scb_waitlist; /* Pending SCB list */ - ips_wait_queue_t copp_waitlist; /* Pending PT list */ + ips_copp_queue_t copp_waitlist; /* Pending PT list */ ips_scb_queue_t scb_activelist; /* Active SCB list */ - BASIC_IO_CMD *dummy; /* dummy command */ - ADAPTER_AREA *adapt; /* Adapter status area */ - ENQCMD *enq; /* Adapter Enquiry data */ - CONFCMD *conf; /* Adapter config data */ - NVRAM_PAGE5 *nvram; /* NVRAM page 5 data */ - SUBSYS_PARAM *subsys; /* Subsystem parameters */ + IPS_IO_CMD *dummy; /* dummy command */ + IPS_ADAPTER *adapt; /* Adapter status area */ + IPS_ENQ *enq; /* Adapter Enquiry data */ + IPS_CONF *conf; /* Adapter config data */ + IPS_NVRAM_P5 *nvram; /* NVRAM page 5 data */ + IPS_SUBSYS *subsys; /* Subsystem parameters */ + char *ioctl_data; /* IOCTL data area */ + u32 ioctl_datasize; /* IOCTL data size */ u32 cmd_in_progress; /* Current command in progress*/ u32 flags; /* HA flags */ u8 waitflag; /* are we waiting for cmd */ u8 active; - u32 reserved:16; /* reserved space */ - wait_queue_head_t copp_queue; /* passthru sync queue */ + u16 reset_count; /* number of resets */ + u32 last_ffdc; /* last time we sent ffdc info*/ + u8 revision_id; /* Revision level */ #if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,0) spinlock_t scb_lock; spinlock_t copp_lock; + spinlock_t ips_lock; #endif } ips_ha_t; -typedef void (*scb_callback) (ips_ha_t *, struct ips_scb *); +typedef void (*ips_scb_callback) (ips_ha_t *, struct ips_scb *); /* * SCB Format */ typedef struct ips_scb { - HOST_COMMAND cmd; - DCDB_TABLE dcdb; + IPS_HOST_COMMAND cmd; + IPS_DCDB_TABLE dcdb; u8 target_id; u8 bus; u8 lun; @@ -794,31 +887,53 @@ u32 sg_len; u32 flags; u32 op_code; - SG_LIST *sg_list; + IPS_SG_LIST *sg_list; Scsi_Cmnd *scsi_cmd; struct ips_scb *q_next; - scb_callback callback; + ips_scb_callback callback; + struct semaphore *sem; } ips_scb_t; +typedef struct ips_scb_pt { + IPS_HOST_COMMAND cmd; + IPS_DCDB_TABLE dcdb; + u8 target_id; + u8 bus; + u8 lun; + u8 cdb[12]; + u32 scb_busaddr; + u32 data_busaddr; + u32 timeout; + u8 basic_status; + u8 extended_status; + u16 breakup; + u32 data_len; + u32 sg_len; + u32 flags; + u32 op_code; + IPS_SG_LIST *sg_list; + Scsi_Cmnd *scsi_cmd; + struct ips_scb *q_next; + ips_scb_callback callback; +} ips_scb_pt_t; + /* * Passthru Command Format */ typedef struct { - u8 CoppID[4]; - u32 CoppCmd; - u32 PtBuffer; - u8 *CmdBuffer; - u32 CmdBSize; - ips_scb_t CoppCP; - u32 TimeOut; - u8 BasicStatus; - u8 ExtendedStatus; - u16 reserved; + u8 CoppID[4]; + u32 CoppCmd; + u32 PtBuffer; + u8 *CmdBuffer; + u32 CmdBSize; + ips_scb_pt_t CoppCP; + u32 TimeOut; + u8 BasicStatus; + u8 ExtendedStatus; + u16 reserved; } ips_passthru_t; #endif - - /* * Overrides for Emacs so that we almost follow Linus's tabbing style. diff -u --recursive --new-file v2.4.0-test5/linux/drivers/scsi/pcmcia/Makefile linux/drivers/scsi/pcmcia/Makefile --- v2.4.0-test5/linux/drivers/scsi/pcmcia/Makefile Wed Feb 16 17:03:52 2000 +++ linux/drivers/scsi/pcmcia/Makefile Sun Aug 6 11:23:40 2000 @@ -8,8 +8,6 @@ MOD_SUB_DIRS := $(SUB_DIRS) ALL_SUB_DIRS := $(SUB_DIRS) -MOD_LIST_NAME := PCMCIA_SCSI_MODULES - obj-y := obj-m := obj-n := diff -u --recursive --new-file v2.4.0-test5/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- v2.4.0-test5/linux/drivers/scsi/scsi.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/scsi/scsi.c Mon Jul 31 11:00:06 2000 @@ -1912,7 +1912,7 @@ * their hosts through the modules entrypoints, and don't use the big * list in hosts.c. */ -#if defined(CONFIG_MODULES) || defined(CONFIG_BLK_DEV_IDESCSI) || defined(CONFIG_USB_STORAGE) /* a big #ifdef block... */ +#if defined(CONFIG_MODULES) || defined(CONFIG_BLK_DEV_IDESCSI) || defined(CONFIG_USB_STORAGE) || defined(CONFIG_USB_MICROTEK) /* a big #ifdef block... */ /* * This entry point should be called by a loadable module if it is trying diff -u --recursive --new-file v2.4.0-test5/linux/drivers/scsi/sg.c linux/drivers/scsi/sg.c --- v2.4.0-test5/linux/drivers/scsi/sg.c Fri Jul 14 12:12:12 2000 +++ linux/drivers/scsi/sg.c Sun Aug 6 11:43:17 2000 @@ -17,8 +17,8 @@ * any later version. * */ - static char * sg_version_str = "Version: 3.1.15 (20000528)"; - static int sg_version_num = 30115; /* 2 digits for each component */ + static char * sg_version_str = "Version: 3.1.16 (20000716)"; + static int sg_version_num = 30116; /* 2 digits for each component */ /* * D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes: * - scsi logging is available via SCSI_LOG_TIMEOUT macros. First @@ -1467,9 +1467,9 @@ } schp->mapped = 1; kp = schp->kiobp; - prev_addr = page_address(kp->maplist[0]); + prev_addr = (unsigned long) page_address(kp->maplist[0]); for (k = 1, split = 0; k < kp->nr_pages; ++k, prev_addr = addr) { - addr = page_address(kp->maplist[k]); + addr = (unsigned long) page_address(kp->maplist[k]); if ((prev_addr + PAGE_SIZE) != addr) { split = k; break; @@ -1477,7 +1477,7 @@ } if (! split) { schp->k_use_sg = 0; - schp->buffer = (void *)(page_address(kp->maplist[0]) + kp->offset); + schp->buffer = page_address(kp->maplist[0]) + kp->offset; schp->bufflen = dxfer_len; schp->buffer_mem_src = SG_USER_MEM; schp->b_malloc_len = dxfer_len; @@ -1497,7 +1497,7 @@ offset = (0 == k) ? kp->offset : 0; num = (rem_sz > (PAGE_SIZE - offset)) ? (PAGE_SIZE - offset) : rem_sz; - sclp->address = (void *)(page_address(kp->maplist[k]) + offset); + sclp->address = page_address(kp->maplist[k]) + offset; sclp->length = num; mem_src_arr[k] = SG_USER_MEM; rem_sz -= num; @@ -1890,9 +1890,9 @@ Sg_scatter_hold * req_schp = &srp->data; Sg_scatter_hold * rsv_schp = &sfp->reserve; + srp->res_used = 1; SCSI_LOG_TIMEOUT(4, printk("sg_link_reserve: size=%d\n", size)); - /* round request up to next highest SG_SECTOR_SZ byte boundary */ - size = (size + SG_SECTOR_MSK) & (~SG_SECTOR_MSK); + size = (size + 1) & (~1); /* round to even for aha1542 */ if (rsv_schp->k_use_sg > 0) { int k, num; int rem = size; @@ -1901,22 +1901,26 @@ for (k = 0; k < rsv_schp->k_use_sg; ++k, ++sclp) { num = (int)sclp->length; if (rem <= num) { - sfp->save_scat_len = num; - sclp->length = (unsigned)rem; - break; + if (0 == k) { + req_schp->k_use_sg = 0; + req_schp->buffer = sclp->address; + } + else { + sfp->save_scat_len = num; + sclp->length = (unsigned)rem; + req_schp->k_use_sg = k + 1; + req_schp->sglist_len = rsv_schp->sglist_len; + req_schp->buffer = rsv_schp->buffer; + } + req_schp->bufflen = size; + req_schp->buffer_mem_src = rsv_schp->buffer_mem_src; + req_schp->b_malloc_len = rsv_schp->b_malloc_len; + break; } else rem -= num; } - if (k < rsv_schp->k_use_sg) { - req_schp->k_use_sg = k + 1; /* adjust scatter list length */ - req_schp->bufflen = size; - req_schp->sglist_len = rsv_schp->sglist_len; - req_schp->buffer = rsv_schp->buffer; - req_schp->buffer_mem_src = rsv_schp->buffer_mem_src; - req_schp->b_malloc_len = rsv_schp->b_malloc_len; - } - else + if (k >= rsv_schp->k_use_sg) SCSI_LOG_TIMEOUT(1, printk("sg_link_reserve: BAD size\n")); } else { @@ -1924,10 +1928,8 @@ req_schp->bufflen = size; req_schp->buffer = rsv_schp->buffer; req_schp->buffer_mem_src = rsv_schp->buffer_mem_src; - req_schp->k_use_sg = rsv_schp->k_use_sg; req_schp->b_malloc_len = rsv_schp->b_malloc_len; } - srp->res_used = 1; } static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp) @@ -1937,7 +1939,7 @@ SCSI_LOG_TIMEOUT(4, printk("sg_unlink_reserve: req->k_use_sg=%d\n", (int)req_schp->k_use_sg)); - if (rsv_schp->k_use_sg > 0) { + if ((rsv_schp->k_use_sg > 0) && (req_schp->k_use_sg > 0)) { struct scatterlist * sclp = (struct scatterlist *)rsv_schp->buffer; if (sfp->save_scat_len > 0) @@ -2118,13 +2120,12 @@ } static int sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp) -{ /* if this is to be locked remember that it is called from _bh */ +{ Sg_request * srp; Sg_request * tsrp; int dirty = 0; int res = 0; - /* no lock since not expecting any parallel action on this fd */ srp = sfp->headrp; if (srp) { while (srp) { diff -u --recursive --new-file v2.4.0-test5/linux/drivers/scsi/st.c linux/drivers/scsi/st.c --- v2.4.0-test5/linux/drivers/scsi/st.c Fri Jul 14 12:12:12 2000 +++ linux/drivers/scsi/st.c Mon Aug 7 22:52:10 2000 @@ -12,10 +12,13 @@ Copyright 1992 - 2000 Kai Makisara email Kai.Makisara@metla.fi - Last modified: Sat Jun 17 15:21:49 2000 by makisara@kai.makisara.local + Last modified: Sun Aug 6 23:02:13 2000 by makisara@kai.makisara.local Some small formal changes - aeb, 950809 Last modified: 18-JAN-1998 Richard Gooch Devfs support + + Reminder: write_lock_irqsave() can be replaced by write_lock() when the old SCSI + error handling will be discarded. */ #include @@ -141,7 +144,7 @@ static int modes_defined; -static ST_buffer *new_tape_buffer(int, int); +static ST_buffer *new_tape_buffer(int, int, int); static int enlarge_buffer(ST_buffer *, int, int); static void normalize_buffer(ST_buffer *); static int append_to_buffer(const char *, ST_buffer *, int); @@ -587,10 +590,11 @@ } -/* Open the device */ -static int scsi_tape_open(struct inode *inode, struct file *filp) +/* Open the device. Needs to be called with BKL only because of incrementing the SCSI host + module count. */ +static int st_open(struct inode *inode, struct file *filp) { - unsigned short flags; + unsigned short st_flags; int i, need_dma_buffer, new_session = FALSE; int retval; unsigned char cmd[MAX_COMMAND_SIZE]; @@ -600,28 +604,32 @@ ST_partstat *STps; int dev = TAPE_NR(inode->i_rdev); int mode = TAPE_MODE(inode->i_rdev); + unsigned long flags; - read_lock(&st_dev_arr_lock); + write_lock_irqsave(&st_dev_arr_lock, flags); STp = scsi_tapes[dev]; if (dev >= st_template.dev_max || STp == NULL) { - read_unlock(&st_dev_arr_lock); + write_unlock_irqrestore(&st_dev_arr_lock, flags); return (-ENXIO); } - read_unlock(&st_dev_arr_lock); - if (!scsi_block_when_processing_errors(STp->device)) { - return -ENXIO; - } if (STp->in_use) { + write_unlock_irqrestore(&st_dev_arr_lock, flags); DEB( printk(ST_DEB_MSG "st%d: Device already in use.\n", dev); ) return (-EBUSY); } STp->in_use = 1; + write_unlock_irqrestore(&st_dev_arr_lock, flags); STp->rew_at_close = STp->autorew_dev = (MINOR(inode->i_rdev) & 0x80) == 0; if (STp->device->host->hostt->module) __MOD_INC_USE_COUNT(STp->device->host->hostt->module); + if (!scsi_block_when_processing_errors(STp->device)) { + retval = (-ENXIO); + goto err_out; + } + if (mode != STp->current_mode) { DEBC(printk(ST_DEB_MSG "st%d: Mode change from %d to %d.\n", dev, STp->current_mode, mode)); @@ -632,16 +640,17 @@ /* Allocate a buffer for this user */ need_dma_buffer = STp->restr_dma; - read_lock(&st_dev_arr_lock); + write_lock_irqsave(&st_dev_arr_lock, flags); for (i = 0; i < st_nbr_buffers; i++) if (!st_buffers[i]->in_use && (!need_dma_buffer || st_buffers[i]->dma)) { STp->buffer = st_buffers[i]; + (STp->buffer)->in_use = 1; break; } - read_unlock(&st_dev_arr_lock); + write_unlock_irqrestore(&st_dev_arr_lock, flags); if (i >= st_nbr_buffers) { - STp->buffer = new_tape_buffer(FALSE, need_dma_buffer); + STp->buffer = new_tape_buffer(FALSE, need_dma_buffer, TRUE); if (STp->buffer == NULL) { printk(KERN_WARNING "st%d: Can't allocate tape buffer.\n", dev); retval = (-EBUSY); @@ -649,7 +658,6 @@ } } - (STp->buffer)->in_use = 1; (STp->buffer)->writing = 0; (STp->buffer)->syscall_result = 0; (STp->buffer)->use_sg = STp->device->host->sg_tablesize; @@ -663,8 +671,8 @@ (STp->buffer)->buffer_size += (STp->buffer)->sg[i].length; } - flags = filp->f_flags; - STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY); + st_flags = filp->f_flags; + STp->write_prot = ((st_flags & O_ACCMODE) == O_RDONLY); STp->dirty = 0; for (i = 0; i < ST_NBR_PARTITIONS; i++) { @@ -813,7 +821,7 @@ DEBC(printk(ST_DEB_MSG "st%d: Write protected\n", dev)); - if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) { + if ((st_flags & O_ACCMODE) == O_WRONLY || (st_flags & O_ACCMODE) == O_RDWR) { retval = (-EROFS); goto err_out; } @@ -864,7 +872,7 @@ /* Flush the tape buffer before close */ -static int scsi_tape_flush(struct file *filp) +static int st_flush(struct file *filp) { int result = 0, result2; unsigned char cmd[MAX_COMMAND_SIZE]; @@ -982,17 +990,18 @@ } -/* Close the device and release it */ -static int scsi_tape_close(struct inode *inode, struct file *filp) +/* Close the device and release it. BKL is not needed: this is the only thread + accessing this tape. */ +static int st_release(struct inode *inode, struct file *filp) { int result = 0; Scsi_Tape *STp; + unsigned long flags; kdev_t devt = inode->i_rdev; int dev; dev = TAPE_NR(devt); - lock_kernel(); read_lock(&st_dev_arr_lock); STp = scsi_tapes[dev]; read_unlock(&st_dev_arr_lock); @@ -1002,13 +1011,18 @@ if (STp->buffer != NULL) { normalize_buffer(STp->buffer); + write_lock_irqsave(&st_dev_arr_lock, flags); (STp->buffer)->in_use = 0; + STp->buffer = NULL; + } + else { + write_lock_irqsave(&st_dev_arr_lock, flags); } STp->in_use = 0; + write_unlock_irqrestore(&st_dev_arr_lock, flags); if (STp->device->host->hostt->module) __MOD_DEC_USE_COUNT(STp->device->host->hostt->module); - unlock_kernel(); return result; } @@ -1452,8 +1466,11 @@ if (SRpnt->sr_sense_buffer[2] & 0x20) { /* ILI */ if (STp->block_size == 0) { - if (transfer <= 0) - transfer = 0; + if (transfer < 0) { + if (STps->drv_block >= 0) + STps->drv_block += 1; + return (-ENOMEM); + } (STp->buffer)->buffer_bytes = bytes - transfer; } else { scsi_release_request(SRpnt); @@ -3112,7 +3129,7 @@ /* Try to allocate a new tape buffer. Calling function must not hold dev_arr_lock. */ static ST_buffer * - new_tape_buffer(int from_initialization, int need_dma) + new_tape_buffer(int from_initialization, int need_dma, int in_use) { int i, priority, b_size, order, got = 0, segs = 0; unsigned long flags; @@ -3205,7 +3222,7 @@ "st: segment sizes: first %d, last %d bytes.\n", tb->sg[0].length, tb->sg[segs - 1].length); ) - tb->in_use = 0; + tb->in_use = in_use; tb->dma = need_dma; tb->buffer_size = got; tb->writing = 0; @@ -3429,9 +3446,9 @@ read: st_read, write: st_write, ioctl: st_ioctl, - open: scsi_tape_open, - flush: scsi_tape_flush, - release: scsi_tape_close, + open: st_open, + flush: st_flush, + release: st_release, }; static int st_attach(Scsi_Device * SDp) @@ -3595,7 +3612,7 @@ if (target_nbr > st_max_buffers) target_nbr = st_max_buffers; for (i=st_nbr_buffers; i < target_nbr; i++) - if (!new_tape_buffer(TRUE, TRUE)) { + if (!new_tape_buffer(TRUE, TRUE, FALSE)) { printk(KERN_INFO "st: Unable to allocate new static buffer.\n"); break; } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/sgi/Makefile linux/drivers/sgi/Makefile --- v2.4.0-test5/linux/drivers/sgi/Makefile Fri Jun 25 17:39:34 1999 +++ linux/drivers/sgi/Makefile Sun Aug 6 11:23:40 2000 @@ -14,7 +14,6 @@ L_OBJS := L_TARGET := sgi.a -MOD_LIST_NAME := SGI_MODULES # Character and Audio devices for SGI machines. # diff -u --recursive --new-file v2.4.0-test5/linux/drivers/sound/Makefile linux/drivers/sound/Makefile --- v2.4.0-test5/linux/drivers/sound/Makefile Fri Jul 14 12:12:12 2000 +++ linux/drivers/sound/Makefile Sun Aug 6 11:23:40 2000 @@ -92,11 +92,11 @@ ifeq ($(CONFIG_DMASOUND),y) SUB_DIRS += dmasound - MOD_SUB_DIRS += dmasound + MOD_IN_SUB_DIRS += dmasound obj-y += dmasound/dmasound.o else ifeq ($(CONFIG_DMASOUND),m) - MOD_SUB_DIRS += dmasound + MOD_IN_SUB_DIRS += dmasound endif endif @@ -148,7 +148,6 @@ # Translate to Rules.make lists. O_TARGET := sounddrivers.o -MOD_LIST_NAME := SOUND_MODULES O_OBJS := $(filter-out $(export-objs), $(obj-y)) OX_OBJS := $(filter $(export-objs), $(obj-y)) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/sound/cmpci.c linux/drivers/sound/cmpci.c --- v2.4.0-test5/linux/drivers/sound/cmpci.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/sound/cmpci.c Mon Aug 7 21:01:36 2000 @@ -109,6 +109,7 @@ #include #include #include +#include #include #include #include @@ -591,13 +592,13 @@ static void dealloc_dmabuf(struct dmabuf *db) { - unsigned long map, mapend; + struct page *pstart, *pend; if (db->rawbuf) { /* undo marking the pages as reserved */ - mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); - for (map = MAP_NR(db->rawbuf); map <= mapend; map++) - clear_bit(PG_reserved, &mem_map[map].flags); + pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); + for (pstart = virt_to_page(db->rawbuf); pstart <= pend; pstart++) + mem_map_unreserve(pstart); free_pages((unsigned long)db->rawbuf, db->buforder); } db->rawbuf = NULL; @@ -614,7 +615,7 @@ int order; unsigned bytepersec; unsigned bufs; - unsigned long map, mapend; + struct page *pstart, *pend; unsigned char fmt; unsigned long flags; @@ -646,9 +647,9 @@ printk(KERN_DEBUG "cmpci: DMA buffer beyond 16MB: busaddr 0x%lx size %ld\n", virt_to_bus(db->rawbuf), PAGE_SIZE << db->buforder); /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */ - mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); - for (map = MAP_NR(db->rawbuf); map <= mapend; map++) - set_bit(PG_reserved, &mem_map[map].flags); + pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); + for (pstart = virt_to_page(db->rawbuf); pstart <= pend; pstart++) + mem_map_reserve(pstart); } bytepersec = rate << sample_shift[fmt]; bufs = PAGE_SIZE << db->buforder; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/sound/dmabuf.c linux/drivers/sound/dmabuf.c --- v2.4.0-test5/linux/drivers/sound/dmabuf.c Wed Apr 26 16:34:08 2000 +++ linux/drivers/sound/dmabuf.c Tue Aug 8 09:11:04 2000 @@ -26,6 +26,7 @@ #define SAMPLE_ROUNDUP 0 #include "sound_config.h" +#include #define DMAP_FREE_ON_CLOSE 0 #define DMAP_KEEP_ON_CLOSE 1 @@ -56,8 +57,9 @@ static int sound_alloc_dmap(struct dma_buffparms *dmap) { char *start_addr, *end_addr; - int i, dma_pagesize; + int dma_pagesize; int sz, size; + struct page *page; dmap->mapping_flags &= ~DMA_MAP_MAPPED; @@ -113,14 +115,15 @@ dmap->raw_buf = start_addr; dmap->raw_buf_phys = virt_to_bus(start_addr); - for (i = MAP_NR(start_addr); i <= MAP_NR(end_addr); i++) - set_bit(PG_reserved, &mem_map[i].flags);; + for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++) + mem_map_reserve(page); return 0; } static void sound_free_dmap(struct dma_buffparms *dmap) { - int sz, size, i; + int sz, size; + struct page *page; unsigned long start_addr, end_addr; if (dmap->raw_buf == NULL) @@ -132,8 +135,8 @@ start_addr = (unsigned long) dmap->raw_buf; end_addr = start_addr + dmap->buffsize; - for (i = MAP_NR(start_addr); i <= MAP_NR(end_addr); i++) - clear_bit(PG_reserved, &mem_map[i].flags);; + for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++) + mem_map_unreserve(page); free_pages((unsigned long) dmap->raw_buf, sz); dmap->raw_buf = NULL; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/sound/emu10k1/audio.c linux/drivers/sound/emu10k1/audio.c --- v2.4.0-test5/linux/drivers/sound/emu10k1/audio.c Fri Jul 14 12:12:12 2000 +++ linux/drivers/sound/emu10k1/audio.c Mon Aug 7 21:01:36 2000 @@ -38,6 +38,7 @@ #include "audio.h" #include #include +#include static void calculate_ofrag(struct woinst *); static void calculate_ifrag(struct wiinst *); @@ -918,7 +919,7 @@ /* Now mark the pages as reserved, otherwise remap_page_range doesn't do what we want */ for (i = 0; i < wave_out->wavexferbuf->numpages; i++) - set_bit(PG_reserved, &mem_map[MAP_NR(wave_out->pagetable[i])].flags); + mem_map_reserve(virt_to_page(wave_out->pagetable[i])); } size = vma->vm_end - vma->vm_start; @@ -1137,7 +1138,7 @@ /* Undo marking the pages as reserved */ for (i = 0; i < woinst->wave_out->wavexferbuf->numpages; i++) - set_bit(PG_reserved, &mem_map[MAP_NR(woinst->wave_out->pagetable[i])].flags); + mem_map_reserve(virt_to_page(woinst->wave_out->pagetable[i])); } woinst->mapped = 0; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c --- v2.4.0-test5/linux/drivers/sound/es1370.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/sound/es1370.c Mon Aug 7 21:01:36 2000 @@ -150,6 +150,7 @@ #include #include #include +#include #include #include #include @@ -540,13 +541,13 @@ extern inline void dealloc_dmabuf(struct es1370_state *s, struct dmabuf *db) { - unsigned long map, mapend; + struct page *page, *pend; if (db->rawbuf) { /* undo marking the pages as reserved */ - mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); - for (map = MAP_NR(db->rawbuf); map <= mapend; map++) - clear_bit(PG_reserved, &mem_map[map].flags); + pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); + for (page = virt_to_page(db->rawbuf); page <= pend; page++) + mem_map_unreserve(page); pci_free_consistent(s->dev, PAGE_SIZE << db->buforder, db->rawbuf, db->dmaaddr); } db->rawbuf = NULL; @@ -558,7 +559,7 @@ int order; unsigned bytepersec; unsigned bufs; - unsigned long map, mapend; + struct page *page, *pend; db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0; if (!db->rawbuf) { @@ -570,9 +571,9 @@ return -ENOMEM; db->buforder = order; /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */ - mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); - for (map = MAP_NR(db->rawbuf); map <= mapend; map++) - set_bit(PG_reserved, &mem_map[map].flags); + pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); + for (page = virt_to_page(db->rawbuf); page <= pend; page++) + mem_map_reserve(page); } fmt &= ES1370_FMT_MASK; bytepersec = rate << sample_shift[fmt]; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/sound/es1371.c linux/drivers/sound/es1371.c --- v2.4.0-test5/linux/drivers/sound/es1371.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/sound/es1371.c Mon Aug 7 21:01:36 2000 @@ -123,6 +123,7 @@ #include #include #include +#include #include #include #include @@ -872,13 +873,13 @@ extern inline void dealloc_dmabuf(struct es1371_state *s, struct dmabuf *db) { - unsigned long map, mapend; + struct page *page, *pend; if (db->rawbuf) { /* undo marking the pages as reserved */ - mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); - for (map = MAP_NR(db->rawbuf); map <= mapend; map++) - clear_bit(PG_reserved, &mem_map[map].flags); + pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); + for (page = virt_to_page(db->rawbuf); page <= pend; page++) + mem_map_unreserve(page); pci_free_consistent(s->dev, PAGE_SIZE << db->buforder, db->rawbuf, db->dmaaddr); } db->rawbuf = NULL; @@ -890,7 +891,7 @@ int order; unsigned bytepersec; unsigned bufs; - unsigned long map, mapend; + struct page *page, *pend; db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0; if (!db->rawbuf) { @@ -902,9 +903,9 @@ return -ENOMEM; db->buforder = order; /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */ - mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); - for (map = MAP_NR(db->rawbuf); map <= mapend; map++) - set_bit(PG_reserved, &mem_map[map].flags); + pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); + for (page = virt_to_page(db->rawbuf); page <= pend; page++) + mem_map_reserve(page); } fmt &= ES1371_FMT_MASK; bytepersec = rate << sample_shift[fmt]; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/sound/esssolo1.c linux/drivers/sound/esssolo1.c --- v2.4.0-test5/linux/drivers/sound/esssolo1.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/sound/esssolo1.c Mon Aug 7 21:01:36 2000 @@ -91,6 +91,7 @@ #include #include #include +#include #include #include @@ -403,13 +404,13 @@ extern inline void dealloc_dmabuf(struct solo1_state *s, struct dmabuf *db) { - unsigned long map, mapend; + struct page *page, *pend; if (db->rawbuf) { /* undo marking the pages as reserved */ - mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); - for (map = MAP_NR(db->rawbuf); map <= mapend; map++) - clear_bit(PG_reserved, &mem_map[map].flags); + pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); + for (page = virt_to_page(db->rawbuf); page <= pend; page++) + mem_map_unreserve(page); pci_free_consistent(s->dev, PAGE_SIZE << db->buforder, db->rawbuf, db->dmaaddr); } db->rawbuf = NULL; @@ -421,7 +422,7 @@ int order; unsigned bytespersec; unsigned bufs, sample_shift = 0; - unsigned long map, mapend; + struct page *page, *pend; db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0; if (!db->rawbuf) { @@ -433,9 +434,9 @@ return -ENOMEM; db->buforder = order; /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */ - mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); - for (map = MAP_NR(db->rawbuf); map <= mapend; map++) - set_bit(PG_reserved, &mem_map[map].flags); + pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); + for (page = virt_to_page(db->rawbuf); page <= pend; page++) + mem_map_reserve(page); } if (s->fmt & (AFMT_S16_LE | AFMT_U16_LE)) sample_shift++; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/sound/i810_audio.c linux/drivers/sound/i810_audio.c --- v2.4.0-test5/linux/drivers/sound/i810_audio.c Fri Jul 14 12:12:12 2000 +++ linux/drivers/sound/i810_audio.c Mon Aug 7 21:01:36 2000 @@ -78,6 +78,7 @@ #include #include #include +#include #include #include @@ -628,7 +629,7 @@ struct dmabuf *dmabuf = &state->dmabuf; void *rawbuf; int order; - unsigned long map, mapend; + struct page *page, *pend; /* alloc as big a chunk as we can, FIXME: is this necessary ?? */ for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) @@ -649,9 +650,9 @@ dmabuf->buforder = order; /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */ - mapend = MAP_NR(rawbuf + (PAGE_SIZE << order) - 1); - for (map = MAP_NR(rawbuf); map <= mapend; map++) - set_bit(PG_reserved, &mem_map[map].flags); + pend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1); + for (page = virt_to_page(rawbuf); page <= pend; page++) + mem_map_reserve(page); return 0; } @@ -660,13 +661,13 @@ static void dealloc_dmabuf(struct i810_state *state) { struct dmabuf *dmabuf = &state->dmabuf; - unsigned long map, mapend; + struct page *page, *pend; if (dmabuf->rawbuf) { /* undo marking the pages as reserved */ - mapend = MAP_NR(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1); - for (map = MAP_NR(dmabuf->rawbuf); map <= mapend; map++) - clear_bit(PG_reserved, &mem_map[map].flags); + pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1); + for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++) + mem_map_unreserve(page); pci_free_consistent(state->card->pci_dev, PAGE_SIZE << dmabuf->buforder, dmabuf->rawbuf, dmabuf->dma_handle); } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/sound/maestro.c linux/drivers/sound/maestro.c --- v2.4.0-test5/linux/drivers/sound/maestro.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/sound/maestro.c Mon Aug 7 21:01:36 2000 @@ -199,6 +199,7 @@ #include #include #include +#include #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) @@ -2819,7 +2820,7 @@ { void *rawbuf=NULL; int order,i; - unsigned long mapend,map; + struct page *page, *pend; /* alloc as big a chunk as we can */ for (order = (dsps_order + (16-PAGE_SHIFT) + 1); order >= (dsps_order + 2 + 1); order--) @@ -2865,17 +2866,16 @@ } /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */ - mapend = MAP_NR(rawbuf + (PAGE_SIZE << order) - 1); - for (map = MAP_NR(rawbuf); map <= mapend; map++) { - set_bit(PG_reserved, &mem_map[map].flags); - } + pend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1); + for (page = virt_to_page(rawbuf); page <= pend; page++) + mem_map_reserve(page); return 0; } static void free_buffers(struct ess_state *s) { - unsigned long map, mapend; + struct page *page, *pend; s->dma_dac.rawbuf = s->dma_adc.rawbuf = NULL; s->dma_dac.mapped = s->dma_adc.mapped = 0; @@ -2884,9 +2884,9 @@ M_printk("maestro: freeing %p\n",s->card->dmapages); /* undo marking the pages as reserved */ - mapend = MAP_NR(s->card->dmapages + (PAGE_SIZE << s->card->dmaorder) - 1); - for (map = MAP_NR(s->card->dmapages); map <= mapend; map++) - clear_bit(PG_reserved, &mem_map[map].flags); + pend = virt_to_page(s->card->dmapages + (PAGE_SIZE << s->card->dmaorder) - 1); + for (page = virt_to_page(s->card->dmapages); page <= pend; page++) + mem_map_unreserve(page); free_pages((unsigned long)s->card->dmapages,s->card->dmaorder); s->card->dmapages = NULL; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/sound/msnd_pinnacle.c linux/drivers/sound/msnd_pinnacle.c --- v2.4.0-test5/linux/drivers/sound/msnd_pinnacle.c Fri Jul 14 12:12:13 2000 +++ linux/drivers/sound/msnd_pinnacle.c Mon Aug 7 21:01:35 2000 @@ -33,6 +33,7 @@ * ********************************************************************/ +#include #include #include #include diff -u --recursive --new-file v2.4.0-test5/linux/drivers/sound/sonicvibes.c linux/drivers/sound/sonicvibes.c --- v2.4.0-test5/linux/drivers/sound/sonicvibes.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/sound/sonicvibes.c Mon Aug 7 21:01:36 2000 @@ -109,6 +109,7 @@ #include #include #include +#include #include #include @@ -692,13 +693,13 @@ static void dealloc_dmabuf(struct sv_state *s, struct dmabuf *db) { - unsigned long map, mapend; + struct page *page, *pend; if (db->rawbuf) { /* undo marking the pages as reserved */ - mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); - for (map = MAP_NR(db->rawbuf); map <= mapend; map++) - clear_bit(PG_reserved, &mem_map[map].flags); + pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); + for (page = virt_to_page(db->rawbuf); page <= pend; page++) + mem_map_unreserve(page); pci_free_consistent(s->dev, PAGE_SIZE << db->buforder, db->rawbuf, db->dmaaddr); } db->rawbuf = NULL; @@ -715,7 +716,7 @@ int order; unsigned bytepersec; unsigned bufs; - unsigned long map, mapend; + struct page *page, *pend; unsigned char fmt; unsigned long flags; @@ -747,9 +748,9 @@ printk(KERN_DEBUG "sv: DMA buffer beyond 16MB: busaddr 0x%lx size %ld\n", virt_to_bus(db->rawbuf), PAGE_SIZE << db->buforder); /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */ - mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); - for (map = MAP_NR(db->rawbuf); map <= mapend; map++) - set_bit(PG_reserved, &mem_map[map].flags); + pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); + for (page = virt_to_page(db->rawbuf); page <= pend; page++) + mem_map_reserve(page); } bytepersec = rate << sample_shift[fmt]; bufs = PAGE_SIZE << db->buforder; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/sound/sscape.c linux/drivers/sound/sscape.c --- v2.4.0-test5/linux/drivers/sound/sscape.c Mon Jul 10 16:47:25 2000 +++ linux/drivers/sound/sscape.c Tue Aug 8 09:11:04 2000 @@ -38,6 +38,7 @@ #include #include #include +#include #include "coproc.h" @@ -810,8 +811,9 @@ static int sscape_alloc_dma(sscape_info *devc) { char *start_addr, *end_addr; - int i, dma_pagesize; + int dma_pagesize; int sz, size; + struct page *page; if (devc->raw_buf != NULL) return 0; /* Already done */ dma_pagesize = (devc->dma < 4) ? (64 * 1024) : (128 * 1024); @@ -848,23 +850,24 @@ devc->raw_buf = start_addr; devc->raw_buf_phys = virt_to_bus(start_addr); - for (i = MAP_NR(start_addr); i <= MAP_NR(end_addr); i++) - set_bit(PG_reserved, &mem_map[i].flags);; + for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++) + mem_map_reserve(page); return 1; } static void sscape_free_dma(sscape_info *devc) { - int sz, size, i; + int sz, size; unsigned long start_addr, end_addr; + struct page *page; if (devc->raw_buf == NULL) return; for (sz = 0, size = PAGE_SIZE; size < devc->buffsize; sz++, size <<= 1); start_addr = (unsigned long) devc->raw_buf; end_addr = start_addr + devc->buffsize; - for (i = MAP_NR(start_addr); i <= MAP_NR(end_addr); i++) - clear_bit(PG_reserved, &mem_map[i].flags);; + for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++) + mem_map_unreserve(page); free_pages((unsigned long) devc->raw_buf, sz); devc->raw_buf = NULL; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/sound/trident.c linux/drivers/sound/trident.c --- v2.4.0-test5/linux/drivers/sound/trident.c Fri Jul 14 12:12:13 2000 +++ linux/drivers/sound/trident.c Mon Aug 7 21:01:36 2000 @@ -109,6 +109,7 @@ #include #include #include +#include #include #include #include @@ -925,7 +926,7 @@ struct dmabuf *dmabuf = &state->dmabuf; void *rawbuf; int order; - unsigned long map, mapend; + struct page *page, *pend; /* alloc as big a chunk as we can, FIXME: is this necessary ?? */ for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) @@ -946,9 +947,9 @@ dmabuf->buforder = order; /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */ - mapend = MAP_NR(rawbuf + (PAGE_SIZE << order) - 1); - for (map = MAP_NR(rawbuf); map <= mapend; map++) - set_bit(PG_reserved, &mem_map[map].flags); + pend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1); + for (page = virt_to_page(rawbuf); page <= pend; page++) + mem_map_reserve(page); return 0; } @@ -957,13 +958,13 @@ static void dealloc_dmabuf(struct trident_state *state) { struct dmabuf *dmabuf = &state->dmabuf; - unsigned long map, mapend; + struct page *page, *pend; if (dmabuf->rawbuf) { /* undo marking the pages as reserved */ - mapend = MAP_NR(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1); - for (map = MAP_NR(dmabuf->rawbuf); map <= mapend; map++) - clear_bit(PG_reserved, &mem_map[map].flags); + pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1); + for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++) + mem_map_unreserve(page); pci_free_consistent(state->card->pci_dev, PAGE_SIZE << dmabuf->buforder, dmabuf->rawbuf, dmabuf->dma_handle); } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/Makefile linux/drivers/usb/Makefile --- v2.4.0-test5/linux/drivers/usb/Makefile Mon Jul 10 16:47:25 2000 +++ linux/drivers/usb/Makefile Sun Aug 6 11:23:40 2000 @@ -14,7 +14,6 @@ O_TARGET := usbdrv.o M_OBJS := O_OBJS := -MOD_LIST_NAME := USB_MODULES # Objects that export symbols. diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/acm.c linux/drivers/usb/acm.c --- v2.4.0-test5/linux/drivers/usb/acm.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/acm.c Thu Jul 27 18:36:54 2000 @@ -689,3 +689,6 @@ module_init(acm_init); module_exit(acm_exit); + +MODULE_AUTHOR("Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik"); +MODULE_DESCRIPTION("USB Abstract Control Model driver for USB modems and ISDN adapters"); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/audio.c linux/drivers/usb/audio.c --- v2.4.0-test5/linux/drivers/usb/audio.c Fri Jul 14 12:12:13 2000 +++ linux/drivers/usb/audio.c Mon Aug 7 21:01:36 2000 @@ -422,7 +422,7 @@ for(nr = 0; nr < NRSGBUF; nr++) { if (!(p = db->sgbuf[nr])) continue; - mem_map_unreserve(MAP_NR(p)); + mem_map_unreserve(virt_to_page(p)); free_page((unsigned long)p); db->sgbuf[nr] = NULL; } @@ -464,7 +464,7 @@ if (!p) return -ENOMEM; db->sgbuf[nr] = p; - mem_map_reserve(MAP_NR(p)); + mem_map_reserve(virt_to_page(p)); } memset(db->sgbuf[nr], AFMT_ISUNSIGNED(db->format) ? 0x80 : 0, PAGE_SIZE); if ((nr << PAGE_SHIFT) >= db->dmasize) @@ -3732,4 +3732,6 @@ usb_deregister(&usb_audio_driver); } +MODULE_AUTHOR("Alan Cox , Thomas Sailer (sailer@ife.ee.ethz.ch)"); +MODULE_DESCRIPTION("USB Audio Class driver"); #endif diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/bluetooth.c linux/drivers/usb/bluetooth.c --- v2.4.0-test5/linux/drivers/usb/bluetooth.c Fri Jul 14 12:12:13 2000 +++ linux/drivers/usb/bluetooth.c Thu Aug 3 17:20:49 2000 @@ -1,11 +1,24 @@ /* - * bluetooth.c Version 0.2 + * bluetooth.c Version 0.3 * * Copyright (c) 2000 Greg Kroah-Hartman + * Copyright (c) 2000 Mark Douglas Corner * * USB Bluetooth driver, based on the Bluetooth Spec version 1.0B * * + * (08/03/2000) Version 0.3 gkh mdc + * Merged in Mark's changes to make the driver play nice with the Axis + * stack. + * Made the write bulk use an urb pool to enable larger transfers with + * fewer calls to the driver. + * Fixed off by one bug in acl pkt receive + * Made packet counters specific to each bluetooth device + * Added checks for zero length callbacks + * Added buffers for int and bulk packets. Had to do this otherwise + * packet types could intermingle. + * Made a control urb pool for the control messages. + * * (07/11/2000) Version 0.2 gkh * Fixed a small bug found by Nils Faerber in the usb_bluetooth_probe * function. @@ -49,17 +62,16 @@ #include #include #include -#include -#include -#include #define DEBUG #include /* Module information */ -MODULE_AUTHOR("Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/"); +MODULE_AUTHOR("Greg Kroah-Hartman, Mark Douglas Corner"); MODULE_DESCRIPTION("USB Bluetooth driver"); +/* define this if you have hardware that is not good */ +/*#define BTBUGGYHARDWARE */ /* Class, SubClass, and Protocol codes that describe a Bluetooth device */ #define WIRELESS_CLASS_CODE 0xe0 @@ -72,19 +84,47 @@ #define USB_BLUETOOTH_MAGIC 0x6d02 /* magic number for bluetooth struct */ +#define BLUETOOTH_CONTROL_REQUEST_TYPE 0x20 + +/* Bluetooth packet types */ +#define CMD_PKT 0x01 +#define ACL_PKT 0x02 +#define SCO_PKT 0x03 +#define EVENT_PKT 0x04 +#define ERROR_PKT 0x05 +#define NEG_PKT 0x06 + +/* Message sizes */ +#define MAX_EVENT_SIZE 0xFF +#define EVENT_HDR_SIZE 3 /* 2 for the header + 1 for the type indicator */ +#define EVENT_BUFFER_SIZE (MAX_EVENT_SIZE + EVENT_HDR_SIZE) + +#define MAX_ACL_SIZE 0xFFFF +#define ACL_HDR_SIZE 5 /* 4 for the header + 1 for the type indicator */ +#define ACL_BUFFER_SIZE (MAX_ACL_SIZE + ACL_HDR_SIZE) + /* parity check flag */ #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) +#define CHAR2INT16(c1,c0) (((u32)((c1) & 0xff) << 8) + (u32)((c0) & 0xff)) +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define NUM_BULK_URBS 24 +#define NUM_CONTROL_URBS 16 struct usb_bluetooth { int magic; struct usb_device * dev; struct tty_driver * tty_driver; /* the tty_driver for this device */ struct tty_struct * tty; /* the coresponding tty for this port */ - + unsigned char minor; /* the starting minor number for this device */ char active; /* someone has this device open */ + int throttle; /* throttled by tty layer */ + + __u8 control_out_bInterfaceNum; + struct urb * control_urb_pool[NUM_CONTROL_URBS]; + devrequest dr[NUM_CONTROL_URBS]; unsigned char * interrupt_in_buffer; struct urb * interrupt_in_urb; @@ -92,17 +132,21 @@ unsigned char * bulk_in_buffer; struct urb * read_urb; - unsigned char * bulk_out_buffer; int bulk_out_size; - struct urb * write_urb; + struct urb * write_urb_pool[NUM_BULK_URBS]; + __u8 bulk_out_endpointAddress; wait_queue_head_t write_wait; struct tq_struct tqueue; /* task queue for line discipline waking up */ + + unsigned int int_packet_pos; + unsigned char int_buffer[EVENT_BUFFER_SIZE]; + unsigned int bulk_packet_pos; + unsigned char bulk_buffer[ACL_BUFFER_SIZE]; /* 64k preallocated, fix? */ }; - /* local function prototypes */ static int bluetooth_open (struct tty_struct *tty, struct file *filp); static void bluetooth_close (struct tty_struct *tty, struct file *filp); @@ -114,9 +158,15 @@ static int bluetooth_ioctl (struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); static void bluetooth_set_termios (struct tty_struct *tty, struct termios *old); +static void bluetooth_int_callback (struct urb *urb); +static void bluetooth_ctrl_callback (struct urb *urb); +static void bluetooth_read_bulk_callback (struct urb *urb); +static void bluetooth_write_bulk_callback (struct urb *urb); + static void * usb_bluetooth_probe (struct usb_device *dev, unsigned int ifnum); static void usb_bluetooth_disconnect (struct usb_device *dev, void *ptr); + static struct usb_driver usb_bluetooth_driver = { name: "bluetooth", probe: usb_bluetooth_probe, @@ -131,6 +181,7 @@ static struct usb_bluetooth *bluetooth_table[BLUETOOTH_TTY_MINORS] = {NULL, }; + static inline int bluetooth_paranoia_check (struct usb_bluetooth *bluetooth, const char *function) { if (!bluetooth) { @@ -141,17 +192,17 @@ dbg("%s - bad magic number for bluetooth", function); return -1; } - + return 0; } -static inline struct usb_bluetooth* get_usb_bluetooth (struct usb_bluetooth *bluetooth, const char *function) -{ +static inline struct usb_bluetooth* get_usb_bluetooth (struct usb_bluetooth *bluetooth, const char *function) +{ if (!bluetooth || - bluetooth_paranoia_check (bluetooth, function)) { + bluetooth_paranoia_check (bluetooth, function)) { /* then say that we dont have a valid usb_bluetooth thing, which will - * end up genrating -ENODEV return values */ + * end up generating -ENODEV return values */ return NULL; } @@ -165,6 +216,54 @@ } +static int bluetooth_ctrl_msg (struct usb_bluetooth *bluetooth, int request, int value, void *buf, int len) +{ + struct urb *urb = NULL; + devrequest *dr = NULL; + int i; + int status; + + dbg (__FUNCTION__); + + /* try to find a free urb in our list */ + for (i = 0; i < NUM_CONTROL_URBS; ++i) { + if (bluetooth->control_urb_pool[i]->status != -EINPROGRESS) { + urb = bluetooth->control_urb_pool[i]; + dr = &bluetooth->dr[i]; + break; + } + } + if (urb == NULL) { + dbg (__FUNCTION__ " - no free urbs"); + return -ENOMEM; + } + + /* free up the last buffer that this urb used */ + if (urb->transfer_buffer != NULL) { + kfree(urb->transfer_buffer); + urb->transfer_buffer = NULL; + } + + dr->requesttype = BLUETOOTH_CONTROL_REQUEST_TYPE; + dr->request = request; + dr->value = cpu_to_le16p(&value); + dr->index = cpu_to_le16p(&bluetooth->control_out_bInterfaceNum); + dr->length = cpu_to_le16p(&len); + + FILL_CONTROL_URB (urb, bluetooth->dev, usb_sndctrlpipe(bluetooth->dev, 0), + (unsigned char*)dr, buf, len, bluetooth_ctrl_callback, 0); + + /* send it down the pipe */ + status = usb_submit_urb(urb); + if (status) + dbg(__FUNCTION__ " - usb_submit_urb(control) failed with status = %d", status); + + return 0; +} + + + + /***************************************************************************** * Driver tty interface functions @@ -172,7 +271,8 @@ static int bluetooth_open (struct tty_struct *tty, struct file * filp) { struct usb_bluetooth *bluetooth; - + int result; + dbg(__FUNCTION__); /* initialize the pointer incase something fails */ @@ -189,16 +289,26 @@ dbg (__FUNCTION__ " - device already open"); return -EINVAL; } - + /* set up our structure making the tty driver remember our object, and us it */ tty->driver_data = bluetooth; bluetooth->tty = tty; - + bluetooth->active = 1; - - /*Start reading from the device*/ - if (usb_submit_urb(bluetooth->read_urb)) - dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed"); + + /* Reset the packet position counters */ + bluetooth->int_packet_pos = 0; + bluetooth->bulk_packet_pos = 0; + +#ifndef BTBUGGYHARDWARE + /* Start reading from the device */ + result = usb_submit_urb(bluetooth->read_urb); + if (result) + dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed with status %d", result); +#endif + result = usb_submit_urb(bluetooth->interrupt_in_urb); + if (result) + dbg(__FUNCTION__ " - usb_submit_urb(interrupt in) failed with status %d", result); return 0; } @@ -207,20 +317,22 @@ static void bluetooth_close (struct tty_struct *tty, struct file * filp) { struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); + int i; if (!bluetooth) { return; } dbg(__FUNCTION__); - + if (!bluetooth->active) { dbg (__FUNCTION__ " - device not opened"); return; } - /* shutdown any bulk reads that might be going on */ - usb_unlink_urb (bluetooth->write_urb); + /* shutdown any bulk reads and writes that might be going on */ + for (i = 0; i < NUM_BULK_URBS; ++i) + usb_unlink_urb (bluetooth->write_urb_pool[i]); usb_unlink_urb (bluetooth->read_urb); bluetooth->active = 0; @@ -230,55 +342,137 @@ static int bluetooth_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count) { struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); - + struct urb *urb = NULL; + unsigned char *new_buffer; + const unsigned char *current_position; + int status; + int bytes_sent; + int buffer_size; + int i; + if (!bluetooth) { return -ENODEV; } - + dbg(__FUNCTION__ " - %d byte(s)", count); if (!bluetooth->active) { dbg (__FUNCTION__ " - device not opened"); return -EINVAL; } - + if (count == 0) { dbg(__FUNCTION__ " - write request of 0 bytes"); - return (0); + return 0; } - - if (bluetooth->write_urb->status == -EINPROGRESS) { - dbg (__FUNCTION__ " - already writing"); - return (0); + if (count == 1) { + dbg(__FUNCTION__ " - write request only included type %d", buf[0]); + return 1; } - count = (count > bluetooth->bulk_out_size) ? bluetooth->bulk_out_size : count; - #ifdef DEBUG - { - int i; - printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ " - length = %d, data = ", count); - for (i = 0; i < count; ++i) { - printk ("%.2x ", buf[i]); - } - printk ("\n"); + printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ " - length = %d, data = ", count); + for (i = 0; i < count; ++i) { + printk ("%.2x ", buf[i]); } + printk ("\n"); #endif - if (from_user) { - copy_from_user(bluetooth->write_urb->transfer_buffer, buf, count); - } - else { - memcpy (bluetooth->write_urb->transfer_buffer, buf, count); - } - - /* send the data out the bulk bluetooth */ - bluetooth->write_urb->transfer_buffer_length = count; + switch (*buf) { + /* First byte indicates the type of packet */ + case CMD_PKT: + /* dbg(__FUNCTION__ "- Send cmd_pkt len:%d", count);*/ + + if (in_interrupt()){ + printk("cmd_pkt from interrupt!\n"); + return count; + } + + new_buffer = kmalloc (count-1, GFP_KERNEL); + + if (!new_buffer) { + err (__FUNCTION__ "- out of memory."); + return -ENOMEM; + } + + if (from_user) + copy_from_user (new_buffer, buf+1, count-1); + else + memcpy (new_buffer, buf+1, count-1); + + bluetooth_ctrl_msg (bluetooth, 0x00, 0x00, new_buffer, count-1); + + /* need to free new_buffer somehow... FIXME */ + return count; + + case ACL_PKT: + current_position = buf; + ++current_position; + --count; + bytes_sent = 0; + + while (count > 0) { + urb = NULL; + + /* try to find a free urb in our list */ + for (i = 0; i < NUM_BULK_URBS; ++i) { + if (bluetooth->write_urb_pool[i]->status != -EINPROGRESS) { + urb = bluetooth->write_urb_pool[i]; + break; + } + } + if (urb == NULL) { + dbg (__FUNCTION__ " - no free urbs"); + return bytes_sent; + } + + /* free up the last buffer that this urb used */ + if (urb->transfer_buffer != NULL) { + kfree(urb->transfer_buffer); + urb->transfer_buffer = NULL; + } + + buffer_size = MIN (count, bluetooth->bulk_out_size); + + new_buffer = kmalloc (buffer_size, GFP_KERNEL); + if (new_buffer == NULL) { + err(__FUNCTION__" no more kernel memory..."); + return bytes_sent; + } + + if (from_user) + copy_from_user(new_buffer, current_position, buffer_size); + else + memcpy (new_buffer, current_position, buffer_size); + + /* build up our urb */ + FILL_BULK_URB (urb, bluetooth->dev, usb_sndbulkpipe(bluetooth->dev, bluetooth->bulk_out_endpointAddress), + new_buffer, buffer_size, bluetooth_write_bulk_callback, bluetooth); + urb->transfer_flags |= USB_QUEUE_BULK; + + /* send it down the pipe */ + status = usb_submit_urb(urb); + if (status) + dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status); +#ifdef BTBUGGYHARDWARE + /* A workaround for the stalled data bug */ + /* May or may not be needed...*/ + if (count != 0) { + udelay(500); + } +#endif + current_position += buffer_size; + bytes_sent += buffer_size; + count -= buffer_size; + } - if (usb_submit_urb(bluetooth->write_urb)) - dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed"); + return bytes_sent + 1; + + default : + dbg(__FUNCTION__" - unsupported (at this time) write type"); + } - return count; + return 0; } @@ -286,21 +480,25 @@ { struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); int room = 0; + int i; if (!bluetooth) { return -ENODEV; } dbg(__FUNCTION__); - + if (!bluetooth->active) { dbg (__FUNCTION__ " - device not open"); return -EINVAL; } - if (bluetooth->write_urb->status != -EINPROGRESS) - room = bluetooth->bulk_out_size; - + for (i = 0; i < NUM_BULK_URBS; ++i) { + if (bluetooth->write_urb_pool[i]->status != -EINPROGRESS) { + room += bluetooth->bulk_out_size; + } + } + dbg(__FUNCTION__ " - returns %d", room); return room; } @@ -310,6 +508,7 @@ { struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); int chars = 0; + int i; if (!bluetooth) { return -ENODEV; @@ -320,9 +519,11 @@ return -EINVAL; } - - if (bluetooth->write_urb->status == -EINPROGRESS) - chars = bluetooth->write_urb->transfer_buffer_length; + for (i = 0; i < NUM_BULK_URBS; ++i) { + if (bluetooth->write_urb_pool[i]->status == -EINPROGRESS) { + chars += bluetooth->write_urb_pool[i]->transfer_buffer_length; + } + } dbg (__FUNCTION__ " - returns %d", chars); return chars; @@ -343,9 +544,9 @@ dbg (__FUNCTION__ " - device not open"); return; } - - /* FIXME!!! */ + dbg(__FUNCTION__ " unsupported (at this time)"); + return; } @@ -365,9 +566,7 @@ return; } - /* FIXME!!! */ - - return; + dbg(__FUNCTION__ " unsupported (at this time)"); } @@ -387,7 +586,6 @@ } /* FIXME!!! */ - return -ENOIOCTLCMD; } @@ -408,59 +606,184 @@ } /* FIXME!!! */ - + return; } +#ifdef BTBUGGYHARDWARE +void btusb_enable_bulk_read(struct tty_struct *tty){ + struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); + + if (!bluetooth) { + return; + } + + dbg(__FUNCTION__); + + if (!bluetooth->active) { + dbg (__FUNCTION__ " - device not open"); + return; + } + + if (bluetooth->read_urb) + if (usb_submit_urb(bluetooth->read_urb)) + dbg (__FUNCTION__ " - usb_submit_urb(read bulk) failed"); +} + +void btusb_disable_bulk_read(struct tty_struct *tty){ + struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); + + if (!bluetooth) { + return; + } + + dbg(__FUNCTION__); + + if (!bluetooth->active) { + dbg (__FUNCTION__ " - device not open"); + return; + } + + if ((bluetooth->read_urb) && (bluetooth->read_urb->actual_length)) + usb_unlink_urb(bluetooth->read_urb); +} +#endif + + /***************************************************************************** * urb callback functions *****************************************************************************/ + static void bluetooth_int_callback (struct urb *urb) { struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__); unsigned char *data = urb->transfer_buffer; - int i; + unsigned int i; + unsigned int count = urb->actual_length; + unsigned int packet_size; dbg(__FUNCTION__); - + if (!bluetooth) { dbg(__FUNCTION__ " - bad bluetooth pointer, exiting"); return; } if (urb->status) { - dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status); + dbg(__FUNCTION__ " - nonzero int status received: %d", urb->status); + return; + } + + if (!count) { + dbg(__FUNCTION__ " - zero length int"); return; } + #ifdef DEBUG - if (urb->actual_length) { - printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ "- length = %d, data = ", urb->actual_length); - for (i = 0; i < urb->actual_length; ++i) { + if (count) { + printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ "- length = %d, data = ", count); + for (i = 0; i < count; ++i) { printk ("%.2x ", data[i]); } printk ("\n"); } #endif - /* Don't really know what else to do with this data yet. */ - /* FIXME!!! */ +#ifdef BTBUGGYHARDWARE + if ((count >= 2) && (data[0] == 0xFF) && (data[1] == 0x00)) { + data += 2; + count -= 2; + } + if (count == 0) { + urb->actual_length = 0; + return; + } +#endif + /* We add a packet type identifier to the beginning of each + HCI frame. This makes the data in the tty look like a + serial USB devices. Each HCI frame can be broken across + multiple URBs so we buffer them until we have a full hci + packet */ + + if (!bluetooth->int_packet_pos) { + bluetooth->int_buffer[0] = EVENT_PKT; + bluetooth->int_packet_pos++; + } - return; + if (bluetooth->int_packet_pos + count > EVENT_BUFFER_SIZE) { + err(__FUNCTION__ " - exceeded EVENT_BUFFER_SIZE"); + bluetooth->int_packet_pos = 0; + return; + } + + memcpy (&bluetooth->int_buffer[bluetooth->int_packet_pos], + urb->transfer_buffer, count); + bluetooth->int_packet_pos += count; + urb->actual_length = 0; + + if (bluetooth->int_packet_pos >= EVENT_HDR_SIZE) + packet_size = bluetooth->int_buffer[2]; + else + return; + + if (packet_size + EVENT_HDR_SIZE < bluetooth->int_packet_pos) { + err(__FUNCTION__ " - packet was too long"); + bluetooth->int_packet_pos = 0; + return; + } + + if (packet_size + EVENT_HDR_SIZE == bluetooth->int_packet_pos){ + for (i = 0; i < bluetooth->int_packet_pos; ++i) + tty_insert_flip_char(bluetooth->tty, bluetooth->int_buffer[i], 0); + tty_flip_buffer_push(bluetooth->tty); + + bluetooth->int_packet_pos = 0; + } +} + + +static void bluetooth_ctrl_callback (struct urb *urb) +{ + struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__); + + dbg(__FUNCTION__); + + if (!bluetooth) { + dbg(__FUNCTION__ " - bad bluetooth pointer, exiting"); + return; + } + + if (urb->status) { + dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status); + return; + } } static void bluetooth_read_bulk_callback (struct urb *urb) { struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__); - struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; - int i; + unsigned int count = urb->actual_length; + unsigned int i; + uint packet_size; + +#ifdef BTBUGGYHARDWARE + if ((count == 4) && (data[0] == 0x00) && (data[1] == 0x00) + && (data[2] == 0x00) && (data[3] == 0x00)) { + urb->actual_length = 0; + if (usb_submit_urb(urb)) + dbg(__FUNCTION__ " - failed resubmitting read urb"); + + return; + } +#endif dbg(__FUNCTION__); - + if (!bluetooth) { dbg(__FUNCTION__ " - bad bluetooth pointer, exiting"); return; @@ -471,25 +794,67 @@ return; } + if (!count) { + dbg(__FUNCTION__ " - zero length read bulk"); + return; + } + #ifdef DEBUG - if (urb->actual_length) { - printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ "- length = %d, data = ", urb->actual_length); - for (i = 0; i < urb->actual_length; ++i) { + if (count) { + printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ "- length = %d, data = ", count); + for (i = 0; i < count; ++i) { printk ("%.2x ", data[i]); } printk ("\n"); } #endif + /* We add a packet type identifier to the beginning of each + HCI frame. This makes the data in the tty look like a + serial USB devices. Each HCI frame can be broken across + multiple URBs so we buffer them until we have a full hci + packet */ + + if (!bluetooth->bulk_packet_pos) { + bluetooth->bulk_buffer[0] = ACL_PKT; + bluetooth->bulk_packet_pos++; + } + + if (bluetooth->bulk_packet_pos + count > ACL_BUFFER_SIZE) { + err(__FUNCTION__ " - exceeded ACL_BUFFER_SIZE"); + bluetooth->bulk_packet_pos = 0; + if (usb_submit_urb(urb)) + dbg(__FUNCTION__ " - failed resubmitting read urb"); + return; + } - tty = bluetooth->tty; - if (urb->actual_length) { - for (i = 0; i < urb->actual_length ; ++i) { - tty_insert_flip_char(tty, data[i], 0); - } - tty_flip_buffer_push(tty); + memcpy (&bluetooth->bulk_buffer[bluetooth->bulk_packet_pos], + urb->transfer_buffer, count); + bluetooth->bulk_packet_pos += count; + urb->actual_length = 0; + + if (bluetooth->bulk_packet_pos >= ACL_HDR_SIZE) { + packet_size = CHAR2INT16(bluetooth->bulk_buffer[4],bluetooth->bulk_buffer[3]); + } else { + if (usb_submit_urb(urb)) + dbg(__FUNCTION__ " - failed resubmitting read urb"); + return; } - /* Continue trying to always read */ + if (packet_size + ACL_HDR_SIZE < bluetooth->bulk_packet_pos) { + err(__FUNCTION__ " - packet was too long"); + bluetooth->bulk_packet_pos = 0; + if (usb_submit_urb(urb)) + dbg(__FUNCTION__ " - failed resubmitting read urb"); + return; + } + + if (packet_size + ACL_HDR_SIZE == bluetooth->bulk_packet_pos) { + for (i = 0; i < bluetooth->bulk_packet_pos; ++i) + tty_insert_flip_char(bluetooth->tty, bluetooth->bulk_buffer[i], 0); + tty_flip_buffer_push(bluetooth->tty); + bluetooth->bulk_packet_pos = 0; + } + if (usb_submit_urb(urb)) dbg(__FUNCTION__ " - failed resubmitting read urb"); @@ -502,7 +867,7 @@ struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__); dbg(__FUNCTION__); - + if (!bluetooth) { dbg(__FUNCTION__ " - bad bluetooth pointer, exiting"); return; @@ -513,9 +878,9 @@ return; } + /* wake up our little function to let the tty layer know that something happened */ queue_task(&bluetooth->tqueue, &tq_immediate); mark_bh(IMMEDIATE_BH); - return; } @@ -526,11 +891,11 @@ struct tty_struct *tty; dbg(__FUNCTION__); - + if (!bluetooth) { return; } - + tty = bluetooth->tty; if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) { dbg(__FUNCTION__ " - write wakeup call."); @@ -549,28 +914,32 @@ struct usb_endpoint_descriptor *interrupt_in_endpoint[8]; struct usb_endpoint_descriptor *bulk_in_endpoint[8]; struct usb_endpoint_descriptor *bulk_out_endpoint[8]; + int control_out_endpoint; + int minor; int buffer_size; int i; int num_interrupt_in = 0; int num_bulk_in = 0; int num_bulk_out = 0; - + /* see if this device has the proper class signature */ if ((dev->descriptor.bDeviceClass != WIRELESS_CLASS_CODE) || (dev->descriptor.bDeviceSubClass != RF_SUBCLASS_CODE) || (dev->descriptor.bDeviceProtocol != BLUETOOTH_PROGRAMMING_PROTOCOL_CODE)) { dbg (__FUNCTION__ " - class signature %d, %d, %d did not match", - dev->descriptor.bDeviceClass, dev->descriptor.bDeviceSubClass, - dev->descriptor.bDeviceProtocol); + dev->descriptor.bDeviceClass, dev->descriptor.bDeviceSubClass, + dev->descriptor.bDeviceProtocol); return NULL; } - /* find the endpoints that we need */ interface = &dev->actconfig->interface[ifnum].altsetting[0]; + control_out_endpoint = interface->bInterfaceNumber; + + /* find the endpoints that we need */ for (i = 0; i < interface->bNumEndpoints; ++i) { endpoint = &interface->endpoint[i]; - + if ((endpoint->bEndpointAddress & 0x80) && ((endpoint->bmAttributes & 3) == 0x02)) { /* we found a bulk in endpoint */ @@ -586,7 +955,7 @@ bulk_out_endpoint[num_bulk_out] = endpoint; ++num_bulk_out; } - + if ((endpoint->bEndpointAddress & 0x80) && ((endpoint->bmAttributes & 3) == 0x03)) { /* we found a interrupt in endpoint */ @@ -595,7 +964,7 @@ ++num_interrupt_in; } } - + /* according to the spec, we can only have 1 bulk_in, 1 bulk_out, and 1 interrupt_in endpoints */ if ((num_bulk_in != 1) || (num_bulk_out != 1) || @@ -603,7 +972,7 @@ dbg (__FUNCTION__ " - improper number of endpoints. Bluetooth driver not bound."); return NULL; } - + MOD_INC_USE_COUNT; info("USB Bluetooth converter detected"); @@ -620,15 +989,29 @@ MOD_DEC_USE_COUNT; return NULL; } - + memset(bluetooth, 0, sizeof(struct usb_bluetooth)); - + bluetooth->magic = USB_BLUETOOTH_MAGIC; bluetooth->dev = dev; bluetooth->minor = minor; bluetooth->tqueue.routine = bluetooth_softint; bluetooth->tqueue.data = bluetooth; + /* record the interface number for the control out */ + bluetooth->control_out_bInterfaceNum = control_out_endpoint; + + /* create our control out urb pool */ + for (i = 0; i < NUM_CONTROL_URBS; ++i) { + struct urb *urb = usb_alloc_urb(0); + if (urb == NULL) { + err("No free urbs available"); + goto probe_error; + } + urb->transfer_buffer = NULL; + bluetooth->control_urb_pool[i] = urb; + } + /* set up the endpoint information */ endpoint = bulk_in_endpoint[0]; bluetooth->read_urb = usb_alloc_urb (0); @@ -646,20 +1029,20 @@ bluetooth->bulk_in_buffer, buffer_size, bluetooth_read_bulk_callback, bluetooth); endpoint = bulk_out_endpoint[0]; - bluetooth->write_urb = usb_alloc_urb(0); - if (!bluetooth->write_urb) { - err("No free urbs available"); - goto probe_error; - } - buffer_size = endpoint->wMaxPacketSize; - bluetooth->bulk_out_size = buffer_size; - bluetooth->bulk_out_buffer = kmalloc (buffer_size, GFP_KERNEL); - if (!bluetooth->bulk_out_buffer) { - err("Couldn't allocate bulk_out_buffer"); - goto probe_error; + bluetooth->bulk_out_endpointAddress = endpoint->bEndpointAddress; + + /* create our write urb pool */ + for (i = 0; i < NUM_BULK_URBS; ++i) { + struct urb *urb = usb_alloc_urb(0); + if (urb == NULL) { + err("No free urbs available"); + goto probe_error; + } + urb->transfer_buffer = NULL; + bluetooth->write_urb_pool[i] = urb; } - FILL_BULK_URB(bluetooth->write_urb, dev, usb_sndbulkpipe(dev, endpoint->bEndpointAddress), - bluetooth->bulk_out_buffer, buffer_size, bluetooth_write_bulk_callback, bluetooth); + + bluetooth->bulk_out_size = endpoint->wMaxPacketSize * 2; endpoint = interrupt_in_endpoint[0]; bluetooth->interrupt_in_urb = usb_alloc_urb(0); @@ -680,9 +1063,9 @@ /* initialize the devfs nodes for this device and let the user know what bluetooths we are bound to */ tty_register_devfs (&bluetooth_tty_driver, 0, minor); info("Bluetooth converter now attached to ttyBLUE%d (or usb/ttblue/%d for devfs)", minor, minor); - + bluetooth_table[minor] = bluetooth; - + return bluetooth; /* success */ probe_error: @@ -690,15 +1073,17 @@ usb_free_urb (bluetooth->read_urb); if (bluetooth->bulk_in_buffer) kfree (bluetooth->bulk_in_buffer); - if (bluetooth->write_urb) - usb_free_urb (bluetooth->write_urb); - if (bluetooth->bulk_out_buffer) - kfree (bluetooth->bulk_out_buffer); if (bluetooth->interrupt_in_urb) usb_free_urb (bluetooth->interrupt_in_urb); if (bluetooth->interrupt_in_buffer) kfree (bluetooth->interrupt_in_buffer); - + for (i = 0; i < NUM_BULK_URBS; ++i) + if (bluetooth->write_urb_pool[i]) + usb_free_urb (bluetooth->write_urb_pool[i]); + for (i = 0; i < NUM_CONTROL_URBS; ++i) + if (bluetooth->control_urb_pool[i]) + usb_free_urb (bluetooth->control_urb_pool[i]); + bluetooth_table[minor] = NULL; /* free up any memory that we allocated */ @@ -711,6 +1096,7 @@ static void usb_bluetooth_disconnect(struct usb_device *dev, void *ptr) { struct usb_bluetooth *bluetooth = (struct usb_bluetooth *) ptr; + int i; if (bluetooth) { bluetooth->active = 0; @@ -721,14 +1107,7 @@ } if (bluetooth->bulk_in_buffer) kfree (bluetooth->bulk_in_buffer); - - if (bluetooth->write_urb) { - usb_unlink_urb (bluetooth->write_urb); - usb_free_urb (bluetooth->write_urb); - } - if (bluetooth->bulk_out_buffer) - kfree (bluetooth->bulk_out_buffer); - + if (bluetooth->interrupt_in_urb) { usb_unlink_urb (bluetooth->interrupt_in_urb); usb_free_urb (bluetooth->interrupt_in_urb); @@ -737,6 +1116,26 @@ kfree (bluetooth->interrupt_in_buffer); tty_unregister_devfs (&bluetooth_tty_driver, bluetooth->minor); + + if (bluetooth->tty) + tty_hangup(bluetooth->tty); + + for (i = 0; i < NUM_BULK_URBS; ++i) { + if (bluetooth->write_urb_pool[i]) { + usb_unlink_urb (bluetooth->write_urb_pool[i]); + if (bluetooth->write_urb_pool[i]->transfer_buffer) + kfree (bluetooth->write_urb_pool[i]->transfer_buffer); + usb_free_urb (bluetooth->write_urb_pool[i]); + } + } + for (i = 0; i < NUM_CONTROL_URBS; ++i) { + if (bluetooth->control_urb_pool[i]) { + usb_unlink_urb (bluetooth->control_urb_pool[i]); + if (bluetooth->control_urb_pool[i]->transfer_buffer) + kfree (bluetooth->control_urb_pool[i]->transfer_buffer); + usb_free_urb (bluetooth->control_urb_pool[i]); + } + } info("Bluetooth converter now disconnected from ttyBLUE%d", bluetooth->minor); @@ -748,7 +1147,7 @@ } else { info("device disconnected"); } - + MOD_DEC_USE_COUNT; } @@ -763,12 +1162,12 @@ type: TTY_DRIVER_TYPE_SERIAL, subtype: SERIAL_TYPE_NORMAL, flags: TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS, - + refcount: &bluetooth_refcount, table: bluetooth_tty, termios: bluetooth_termios, termios_locked: bluetooth_termios_locked, - + open: bluetooth_open, close: bluetooth_close, write: bluetooth_write, @@ -808,7 +1207,7 @@ err("usb_register failed for the USB bluetooth driver. Error number %d", result); return -1; } - + return 0; } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/dabusb.c linux/drivers/usb/dabusb.c --- v2.4.0-test5/linux/drivers/usb/dabusb.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/dabusb.c Thu Jul 27 18:36:54 2000 @@ -841,6 +841,7 @@ MODULE_AUTHOR ("Deti Fliegl, deti@fliegl.de"); MODULE_DESCRIPTION ("DAB-USB Interface Driver for Linux (c)1999"); MODULE_PARM (buffers, "i"); +MODULE_PARM_DESC (buffers, "Number of buffers (default=256)"); int __init init_module (void) { diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/dsbr100.c linux/drivers/usb/dsbr100.c --- v2.4.0-test5/linux/drivers/usb/dsbr100.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/dsbr100.c Thu Jul 27 18:36:54 2000 @@ -347,6 +347,9 @@ usb_deregister(&usb_dsbr100_driver); } +MODULE_AUTHOR("Markus Demleitner "); +MODULE_DESCRIPTION("D-Link DSB-R100 USB radio driver"); + /* vi: ts=8 Sigh. Of course, I am one of the ts=2 heretics, but Linus' wish is diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/evdev.c linux/drivers/usb/evdev.c --- v2.4.0-test5/linux/drivers/usb/evdev.c Fri Jul 14 12:12:13 2000 +++ linux/drivers/usb/evdev.c Thu Jul 27 18:36:54 2000 @@ -351,3 +351,6 @@ module_init(evdev_init); module_exit(evdev_exit); + +MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_DESCRIPTION("Event character device driver"); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/hid.c linux/drivers/usb/hid.c --- v2.4.0-test5/linux/drivers/usb/hid.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/hid.c Thu Jul 27 18:36:54 2000 @@ -1524,3 +1524,6 @@ module_init(hid_init); module_exit(hid_exit); + +MODULE_AUTHOR("Andreas Gal, Vojtech Pavlik "); +MODULE_DESCRIPTION("USB HID support drivers"); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/ibmcam.c linux/drivers/usb/ibmcam.c --- v2.4.0-test5/linux/drivers/usb/ibmcam.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/ibmcam.c Mon Aug 7 21:01:36 2000 @@ -127,21 +127,36 @@ static int init_model2_yb = -1; MODULE_PARM(debug, "i"); +MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); MODULE_PARM(flags, "i"); +MODULE_PARM_DESC(flags, "Bitfield: 0=VIDIOCSYNC, 1=B/W, 2=show hints, 3=show stats, 4=test pattern, 5=seperate frames, 6=clean frames"); MODULE_PARM(framerate, "i"); +MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)"); MODULE_PARM(lighting, "i"); +MODULE_PARM_DESC(lighting, "Photosensitivity: 0=bright, 1=medium (default), 2=low light"); MODULE_PARM(sharpness, "i"); +MODULE_PARM_DESC(sharpness, "Model1 noise reduction: 0=smooth, 6=sharp (default=4)"); MODULE_PARM(videosize, "i"); +MODULE_PARM_DESC(videosize, "Image size: 0=128x96, 1=176x144, 2=352x288, 3=320x240, 4=352x240 (default=1)"); MODULE_PARM(init_brightness, "i"); +MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)"); MODULE_PARM(init_contrast, "i"); +MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)"); MODULE_PARM(init_color, "i"); +MODULE_PARM_DESC(init_color, "Dolor preconfiguration: 0-255 (default=128)"); MODULE_PARM(init_hue, "i"); +MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)"); MODULE_PARM(hue_correction, "i"); +MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)"); MODULE_PARM(init_model2_rg, "i"); +MODULE_PARM_DESC(init_model2_rg, "Model2 preconfiguration: 0-255 (default=112)"); MODULE_PARM(init_model2_rg2, "i"); +MODULE_PARM_DESC(init_model2_rg2, "Model2 preconfiguration: 0-255 (default=47)"); MODULE_PARM(init_model2_sat, "i"); +MODULE_PARM_DESC(init_model2_sat, "Model2 preconfiguration: 0-255 (default=52)"); MODULE_PARM(init_model2_yb, "i"); +MODULE_PARM_DESC(init_model2_yb, "Model2 preconfiguration: 0-255 (default=160)"); MODULE_AUTHOR ("module author"); MODULE_DESCRIPTION ("IBM/Xirlink C-it USB Camera Driver for Linux (c) 2000"); @@ -190,8 +205,10 @@ if (!pmd_none(*pmd)) { ptep = pte_offset(pmd, adr); pte = *ptep; - if (pte_present(pte)) - ret = page_address(pte_page(pte)) | (adr & (PAGE_SIZE-1)); + if (pte_present(pte)) { + ret = (unsigned long) page_address(pte_page(pte)); + ret |= (adr & (PAGE_SIZE - 1)); + } } } MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret)); @@ -251,7 +268,7 @@ adr = (unsigned long) mem; while (size > 0) { page = kvirt_to_pa(adr); - mem_map_reserve(MAP_NR(__va(page))); + mem_map_reserve(virt_to_page(__va(page))); adr += PAGE_SIZE; if (size > PAGE_SIZE) size -= PAGE_SIZE; @@ -275,7 +292,7 @@ adr=(unsigned long) mem; while (size > 0) { page = kvirt_to_pa(adr); - mem_map_unreserve(MAP_NR(__va(page))); + mem_map_unreserve(virt_to_page(__va(page))); adr += PAGE_SIZE; if (size > PAGE_SIZE) size -= PAGE_SIZE; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/iforce.c linux/drivers/usb/iforce.c --- v2.4.0-test5/linux/drivers/usb/iforce.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/iforce.c Thu Jul 27 18:36:54 2000 @@ -38,6 +38,7 @@ #include MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_DESCRIPTION("USB/RS232 I-Force joysticks and wheels driver"); #define USB_VENDOR_ID_LOGITECH 0x046d #define USB_DEVICE_ID_LOGITECH_WMFORCE 0xc281 diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/input.c linux/drivers/usb/input.c --- v2.4.0-test5/linux/drivers/usb/input.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/input.c Thu Jul 27 18:36:54 2000 @@ -34,6 +34,7 @@ #include MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_DESCRIPTION("Input layer module"); EXPORT_SYMBOL(input_register_device); EXPORT_SYMBOL(input_unregister_device); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/joydev.c linux/drivers/usb/joydev.c --- v2.4.0-test5/linux/drivers/usb/joydev.c Fri Jul 14 12:12:13 2000 +++ linux/drivers/usb/joydev.c Thu Jul 27 18:36:54 2000 @@ -83,6 +83,7 @@ static struct joydev *joydev_table[JOYDEV_MINORS]; MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_DESCRIPTION("Joystick device driver"); MODULE_SUPPORTED_DEVICE("input/js"); static int joydev_correct(int value, struct js_corr *corr) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/keybdev.c linux/drivers/usb/keybdev.c --- v2.4.0-test5/linux/drivers/usb/keybdev.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/keybdev.c Thu Jul 27 18:36:54 2000 @@ -195,3 +195,6 @@ module_init(keybdev_init); module_exit(keybdev_exit); + +MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_DESCRIPTION("Input driver to keyboard driver binding"); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/microtek.c linux/drivers/usb/microtek.c --- v2.4.0-test5/linux/drivers/usb/microtek.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/microtek.c Thu Jul 27 18:36:54 2000 @@ -1050,3 +1050,6 @@ module_init(microtek_drv_init); module_exit(microtek_drv_exit); + +MODULE_AUTHOR("John Fremlin , Oliver Neukum "); +MODULE_DESCRIPTION("Microtek Scanmaker X6 USB scanner driver"); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/mousedev.c linux/drivers/usb/mousedev.c --- v2.4.0-test5/linux/drivers/usb/mousedev.c Fri Jul 14 12:12:13 2000 +++ linux/drivers/usb/mousedev.c Thu Jul 27 18:36:54 2000 @@ -481,3 +481,6 @@ module_init(mousedev_init); module_exit(mousedev_exit); + +MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_DESCRIPTION("Input driver to PS/2 or ImPS/2 device driver"); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/ov511.c linux/drivers/usb/ov511.c --- v2.4.0-test5/linux/drivers/usb/ov511.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/ov511.c Mon Aug 7 21:01:36 2000 @@ -108,16 +108,27 @@ static int retry_sync = 0; MODULE_PARM(autoadjust, "i"); +MODULE_PARM_DESC(autoadjust, "CCD dynamically changes exposure"); MODULE_PARM(debug, "i"); +MODULE_PARM_DESC(debug, "Debug level: 0=none, 1=init/detection, 2=warning, 3=config/control, 4=function call, 5=max"); MODULE_PARM(fix_rgb_offset, "i"); +MODULE_PARM_DESC(fix_rgb_offset, "Fix vertical misalignment of red and blue at 640x480"); MODULE_PARM(snapshot, "i"); +MODULE_PARM_DESC(snapshot, "Enable snapshot mode"); MODULE_PARM(sensor, "i"); +MODULE_PARM_DESC(sensor, "Override sensor detection"); MODULE_PARM(i2c_detect_tries, "i"); +MODULE_PARM_DESC(i2c_detect_tries, "Number of tries to detect sensor"); MODULE_PARM(aperture, "i"); +MODULE_PARM_DESC(aperture, "Read the OV7610/7620 specs"); MODULE_PARM(force_rgb, "i"); +MODULE_PARM_DESC(force_rgb, "Read RBG instead of BGR"); MODULE_PARM(buf_timeout, "i"); +MODULE_PARM_DESC(buf_timeout, "Number of seconds before buffer deallocation"); MODULE_PARM(cams, "i"); +MODULE_PARM_DESC(cams, "Number of simultaneous cameras"); MODULE_PARM(retry_sync, "i"); +MODULE_PARM_DESC(retry_sync, "Prevent apps from timing out"); MODULE_AUTHOR("Mark McClelland & Bret Wallach & Orion Sky Lawlor & Kevin Moore & Charl P. Botha & Claudio Matsuoka "); MODULE_DESCRIPTION("OV511 USB Camera Driver"); @@ -196,9 +207,10 @@ if (!pmd_none(*pmd)) { ptep = pte_offset(pmd, adr); pte = *ptep; - if (pte_present(pte)) - ret = page_address(pte_page(pte)) | - (adr & (PAGE_SIZE-1)); + if (pte_present(pte)) { + ret = (unsigned long) page_address(pte_page(pte)); + ret |= (adr & (PAGE_SIZE - 1)); + } } } @@ -236,7 +248,7 @@ adr = (unsigned long) mem; while (size > 0) { page = kvirt_to_pa(adr); - mem_map_reserve(MAP_NR(__va(page))); + mem_map_reserve(virt_to_page(__va(page))); adr += PAGE_SIZE; if (size > PAGE_SIZE) size -= PAGE_SIZE; @@ -260,7 +272,7 @@ adr=(unsigned long) mem; while (size > 0) { page = kvirt_to_pa(adr); - mem_map_unreserve(MAP_NR(__va(page))); + mem_map_unreserve(virt_to_page(__va(page))); adr += PAGE_SIZE; if (size > PAGE_SIZE) size -= PAGE_SIZE; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/pegasus.c linux/drivers/usb/pegasus.c --- v2.4.0-test5/linux/drivers/usb/pegasus.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/pegasus.c Thu Jul 27 18:36:54 2000 @@ -103,7 +103,7 @@ MODULE_AUTHOR("Petko Manolov "); MODULE_DESCRIPTION("ADMtek AN986 Pegasus USB Ethernet driver"); MODULE_PARM(loopback, "i"); - +MODULE_PARM_DESC(loopback, "Enable loopback mode (Bit 0) and ??? (Bit 1)"); static struct usb_eth_dev usb_dev_id[] = { {"Billionton USB-100", 0x08dd, 0x0986, NULL}, diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/printer.c linux/drivers/usb/printer.c --- v2.4.0-test5/linux/drivers/usb/printer.c Fri Jul 14 12:12:13 2000 +++ linux/drivers/usb/printer.c Thu Jul 27 18:36:54 2000 @@ -527,3 +527,6 @@ module_init(usblp_init); module_exit(usblp_exit); + +MODULE_AUTHOR("Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap"); +MODULE_DESCRIPTION("USB Printer Device Class driver"); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/rio500.c linux/drivers/usb/rio500.c --- v2.4.0-test5/linux/drivers/usb/rio500.c Wed Apr 26 16:34:08 2000 +++ linux/drivers/usb/rio500.c Thu Jul 27 18:36:54 2000 @@ -445,3 +445,5 @@ module_init(usb_rio_init); module_exit(usb_rio_cleanup); +MODULE_AUTHOR("Cesar Miquel "); +MODULE_DESCRIPTION("USB Rio 500 driver"); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/serial/Makefile linux/drivers/usb/serial/Makefile --- v2.4.0-test5/linux/drivers/usb/serial/Makefile Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/serial/Makefile Sun Aug 6 11:23:40 2000 @@ -5,7 +5,6 @@ O_TARGET := usb-serial.o M_OBJS := O_OBJS := -MOD_LIST_NAME := USB_SERIAL_MODULES # Object file lists. @@ -14,13 +13,7 @@ obj-n := obj- := -ifeq ($(CONFIG_USB_SERIAL),y) - obj-y += usbserial.o -endif -ifeq ($(CONFIG_USB_SERIAL),m) - obj-m += usbserial.o -endif - +obj-$(CONFIG_USB_SERIAL) += usbserial.o obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o obj-$(CONFIG_USB_SERIAL_FTDI_SIO) += ftdi_sio.o diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/serial/digi_acceleport.c linux/drivers/usb/serial/digi_acceleport.c --- v2.4.0-test5/linux/drivers/usb/serial/digi_acceleport.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/serial/digi_acceleport.c Thu Jul 27 18:36:54 2000 @@ -1768,4 +1768,6 @@ module_init(digi_init); module_exit(digi_exit); +MODULE_AUTHOR("Peter Berger , Al Borchers "); +MODULE_DESCRIPTION("Digi AccelePort USB-4 Serial Converter driver"); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/serial/ftdi_sio.c linux/drivers/usb/serial/ftdi_sio.c --- v2.4.0-test5/linux/drivers/usb/serial/ftdi_sio.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/serial/ftdi_sio.c Thu Jul 27 18:36:54 2000 @@ -741,3 +741,5 @@ module_init(ftdi_sio_init); module_exit(ftdi_sio_exit); +MODULE_AUTHOR("Greg Kroah-Hartman , Bill Ryder "); +MODULE_DESCRIPTION("USB FTDI SIO driver"); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/serial/keyspan.c linux/drivers/usb/serial/keyspan.c --- v2.4.0-test5/linux/drivers/usb/serial/keyspan.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/serial/keyspan.c Thu Jul 27 18:36:54 2000 @@ -721,3 +721,5 @@ module_init(keyspan_init); module_exit(keyspan_exit); +MODULE_AUTHOR("Hugh Blemings "); +MODULE_DESCRIPTION("Keyspan USB to Serial Converter driver"); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/serial/keyspan_pda.c linux/drivers/usb/serial/keyspan_pda.c --- v2.4.0-test5/linux/drivers/usb/serial/keyspan_pda.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/serial/keyspan_pda.c Thu Jul 27 18:36:54 2000 @@ -720,3 +720,5 @@ module_init(keyspan_pda_init); module_exit(keyspan_pda_exit); +MODULE_AUTHOR("Brian Warner "); +MODULE_DESCRIPTION("USB Keyspan PDA Converter driver"); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/serial/visor.c linux/drivers/usb/serial/visor.c --- v2.4.0-test5/linux/drivers/usb/serial/visor.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/serial/visor.c Thu Jul 27 18:36:54 2000 @@ -434,3 +434,5 @@ module_init(visor_init); module_exit(visor_exit); +MODULE_AUTHOR("Greg Kroah-Hartman "); +MODULE_DESCRIPTION("USB HandSpring Visor driver"); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/serial/whiteheat.c linux/drivers/usb/serial/whiteheat.c --- v2.4.0-test5/linux/drivers/usb/serial/whiteheat.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/serial/whiteheat.c Thu Jul 27 18:36:54 2000 @@ -549,3 +549,5 @@ module_init(whiteheat_init); module_exit(whiteheat_exit); +MODULE_AUTHOR("Greg Kroah-Hartman "); +MODULE_DESCRIPTION("USB ConnectTech WhiteHEAT driver"); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/storage/Makefile linux/drivers/usb/storage/Makefile --- v2.4.0-test5/linux/drivers/usb/storage/Makefile Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/storage/Makefile Sun Aug 6 11:23:41 2000 @@ -5,25 +5,25 @@ O_TARGET := usb-storage.o M_OBJS := usb-storage.o O_OBJS := scsiglue.o protocol.o transport.o usb.o -MOD_LIST_NAME := USB_STORAGE_MODULES CFLAGS_scsiglue.o:= -I../../scsi/ CFLAGS_protocol.o:= -I../../scsi/ CFLAGS_transport.o:= -I../../scsi/ CFLAGS_debug.o:= -I../../scsi/ CFLAGS_usb.o:= -I../../scsi/ -CFLAGS_scm.o:= -I../../scsi/ +CFLAGS_shuttle_usbat.o:= -I../../scsi/ +CFLAGS_sddr09.o:= -I../../scsi/ ifeq ($(CONFIG_USB_STORAGE_DEBUG),y) O_OBJS += debug.o endif ifeq ($(CONFIG_USB_STORAGE_HP8200e),y) - O_OBJS += scm.o + O_OBJS += shuttle_usbat.o endif ifeq ($(CONFIG_USB_STORAGE_SDDR09),y) - O_OBJS += scm.o + O_OBJS += sddr09.o endif ifeq ($(CONFIG_USB_STORAGE_FREECOM),y) diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/storage/protocol.c linux/drivers/usb/storage/protocol.c --- v2.4.0-test5/linux/drivers/usb/storage/protocol.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/storage/protocol.c Tue Aug 1 18:54:58 2000 @@ -1,6 +1,6 @@ /* Driver for USB Mass Storage compliant devices * - * $Id: protocol.c,v 1.2 2000/07/19 17:21:39 groovyjava Exp $ + * $Id: protocol.c,v 1.4 2000/08/01 22:01:19 mdharm Exp $ * * Current development and maintainance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -50,9 +50,58 @@ #include "transport.h" /*********************************************************************** + * Helper routines + ***********************************************************************/ + +/* Fix-up the return data from an INQUIRY command to show + * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us + */ +void fix_inquiry_data(Scsi_Cmnd *srb) +{ + unsigned char *data_ptr; + + /* verify that it's an INQUIRY command */ + if (srb->cmnd[0] != INQUIRY) + return; + + US_DEBUGP("Fixing INQUIRY data to show SCSI rev 2\n"); + + /* find the location of the data */ + if (srb->use_sg) { + struct scatterlist *sg; + + sg = (struct scatterlist *) srb->request_buffer; + data_ptr = (unsigned char *) sg[0].address; + } else + data_ptr = (unsigned char *)srb->request_buffer; + + /* Change the SCSI revision number */ + data_ptr[2] |= 0x2; +} + +/*********************************************************************** * Protocol routines ***********************************************************************/ +void usb_stor_qic157_command(Scsi_Cmnd *srb, struct us_data *us) +{ + /* Pad the ATAPI command with zeros + * NOTE: This only works because a Scsi_Cmnd struct field contains + * a unsigned char cmnd[12], so we know we have storage available + */ + for (; srb->cmd_len<12; srb->cmd_len++) + srb->cmnd[srb->cmd_len] = 0; + + /* set command length to 12 bytes */ + srb->cmd_len = 12; + + /* send the command to the transport layer */ + usb_stor_invoke_transport(srb, us); + + /* fix the INQUIRY data if necessary */ + fix_inquiry_data(srb); +} + void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us) { int old_cmnd = 0; @@ -65,7 +114,6 @@ */ /* Pad the ATAPI command with zeros */ - for (; srb->cmd_len<12; srb->cmd_len++) srb->cmnd[srb->cmd_len] = 0; @@ -125,12 +173,8 @@ if ((old_cmnd == MODE_SENSE) && (srb->result == GOOD)) usb_stor_scsiSense10to6(srb); - /* Fix-up the return data from an INQUIRY command to show - * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us - */ - if (srb->cmnd[0] == INQUIRY) { - ((unsigned char *)us->srb->request_buffer)[2] |= 0x2; - } + /* fix the INQUIRY data if necessary */ + fix_inquiry_data(srb); } @@ -224,12 +268,8 @@ if ((old_cmnd == MODE_SENSE) && (srb->result == GOOD)) usb_stor_scsiSense10to6(srb); - /* Fix-up the return data from an INQUIRY command to show - * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us - */ - if (srb->cmnd[0] == INQUIRY) { - ((unsigned char *)us->srb->request_buffer)[2] |= 0x2; - } + /* Fix the data for an INQUIRY, if necessary */ + fix_inquiry_data(srb); } void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us) @@ -300,10 +340,7 @@ /* send the command to the transport layer */ usb_stor_invoke_transport(srb, us); - /* fix the results of an INQUIRY */ - if (srb->cmnd[0] == INQUIRY) { - US_DEBUGP("Fixing INQUIRY data, setting SCSI rev to 2\n"); - ((unsigned char*)us->srb->request_buffer)[2] |= 2; - } + /* fix the INQUIRY data if necessary */ + fix_inquiry_data(srb); } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/storage/protocol.h linux/drivers/usb/storage/protocol.h --- v2.4.0-test5/linux/drivers/usb/storage/protocol.h Mon Jul 10 16:47:25 2000 +++ linux/drivers/usb/storage/protocol.h Tue Aug 1 18:54:58 2000 @@ -1,7 +1,7 @@ /* Driver for USB Mass Storage compliant devices * Protocol Functions Header File * - * $Id: protocol.h,v 1.1 2000/06/27 01:25:28 mdharm Exp $ + * $Id: protocol.h,v 1.2 2000/08/01 22:01:19 mdharm Exp $ * * Current development and maintainance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -57,6 +57,7 @@ #define US_SC_MAX US_SC_SCSI extern void usb_stor_ATAPI_command(Scsi_Cmnd*, struct us_data*); +extern void usb_stor_qic157_command(Scsi_Cmnd*, struct us_data*); extern void usb_stor_ufi_command(Scsi_Cmnd*, struct us_data*); extern void usb_stor_transparent_scsi_command(Scsi_Cmnd*, struct us_data*); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/storage/scm.c linux/drivers/usb/storage/scm.c --- v2.4.0-test5/linux/drivers/usb/storage/scm.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/storage/scm.c Wed Dec 31 16:00:00 1969 @@ -1,1156 +0,0 @@ -/* Driver for SCM Microsystems USB-ATAPI cable - * - * $Id: scm.c,v 1.4 2000/07/24 19:19:52 mdharm Exp $ - * - * SCM driver v0.2: - * - * Removed any reference to maxlen for bulk transfers. - * Changed scm_bulk_transport to allow for transfers without commands. - * Changed hp8200e transport to use the request_bufflen field in the - * SCSI command for the length of the transfer, rather than calculating - * it ourselves based on the command. - * - * SCM driver v0.1: - * - * First release - hp8200e. - * - * Current development and maintainance by: - * (c) 2000 Robert Baruch (autophile@dol.net) - * - * Many originally ATAPI devices were slightly modified to meet the USB - * market by using some kind of translation from ATAPI to USB on the host, - * and the peripheral would translate from USB back to ATAPI. - * - * SCM Microsystems (www.scmmicro.com) makes a device, sold to OEM's only, - * which does the USB-to-ATAPI conversion. By obtaining the data sheet on - * their device under nondisclosure agreement, I have been able to write - * this driver for Linux. - * - * The chip used in the device can also be used for EPP and ISA translation - * as well. This driver is only guaranteed to work with the ATAPI - * translation. - * - * The only peripherals that I know of (as of 14 Jul 2000) that uses this - * device is the Hewlett-Packard 8200e CD-Writer Plus. - * - * 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, 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. - */ - -#include "transport.h" -#include "protocol.h" -#include "usb.h" -#include "debug.h" -#include "scm.h" - -#include -#include -#include - -extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe, - u8 request, u8 requesttype, u16 value, u16 index, - void *data, u16 size); -extern int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe, - unsigned int len, unsigned int *act_len); - -/* - * Send a control message and wait for the response. - * - * us - the pointer to the us_data structure for the device to use - * - * request - the URB Setup Packet's first 6 bytes. The first byte always - * corresponds to the request type, and the second byte always corresponds - * to the request. The other 4 bytes do not correspond to value and index, - * since they are used in a custom way by the SCM protocol. - * - * xfer_data - a buffer from which to get, or to which to store, any data - * that gets send or received, respectively, with the URB. Even though - * it looks like we allocate a buffer in this code for the data, xfer_data - * must contain enough allocated space. - * - * xfer_len - the number of bytes to send or receive with the URB. - * - */ - -static int scm_send_control(struct us_data *us, - unsigned char command[8], - unsigned char *xfer_data, - unsigned int xfer_len) { - - int result; - int pipe; - void *buffer = NULL; - - command[6] = xfer_len&0xFF; - command[7] = (xfer_len>>8)&0xFF; - - // Get the receive or send control pipe number, based on - // the direction indicated by the request type. - - if (command[0] & USB_DIR_IN) - pipe = usb_rcvctrlpipe(us->pusb_dev,0); - else - pipe = usb_sndctrlpipe(us->pusb_dev,0); - - - // If data is going to be sent or received with the URB, - // then allocate a buffer for it. If data is to be sent, - // copy the data into the buffer. - - if (xfer_len > 0) { - buffer = kmalloc(xfer_len, GFP_KERNEL); - if (!(command[0] & USB_DIR_IN)) - memcpy(buffer, xfer_data, xfer_len); - } - - // Send the URB to the device and wait for a response. - - /* Why are request and request type reversed in this call? */ - - result = usb_stor_control_msg(us, pipe, - command[1], command[0], - (((unsigned short)command[3])<<8) | command[2], - (((unsigned short)command[5])<<8) | command[3], - buffer, - xfer_len); - - - // If data was sent or received with the URB, free the buffer we - // allocated earlier, but not before reading the data out of the - // buffer if we wanted to receive data. - - if (xfer_len > 0) { - if (command[0] & USB_DIR_IN) - memcpy(xfer_data, buffer, xfer_len); - kfree(buffer); - } - - // Check the return code for the command. - - if (result < 0) { - /* a stall is a fatal condition from the device */ - if (result == -EPIPE) { - US_DEBUGP("-- Stall on control pipe. Clearing\n"); - result = usb_clear_halt(us->pusb_dev, pipe); - US_DEBUGP("-- usb_clear_halt() returns %d\n", result); - return USB_STOR_TRANSPORT_FAILED; - } - - /* Uh oh... serious problem here */ - return USB_STOR_TRANSPORT_ERROR; - } - - return USB_STOR_TRANSPORT_GOOD; -} - -static int scm_raw_bulk(struct us_data *us, - int direction, - unsigned char *data, - unsigned short len) { - - int result; - int act_len; - int pipe; - - if (direction == SCSI_DATA_READ) - pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); - else - pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out); - - result = usb_stor_bulk_msg(us, data, pipe, len, &act_len); - - /* if we stall, we need to clear it before we go on */ - if (result == -EPIPE) { - US_DEBUGP("EPIPE: clearing endpoint halt for" - " pipe 0x%x, stalled at %d bytes\n", - pipe, act_len); - usb_clear_halt(us->pusb_dev, pipe); - } - - if (result) { - - /* NAK - that means we've retried a few times already */ - if (result == -ETIMEDOUT) { - US_DEBUGP("scm_raw_bulk():" - " device NAKed\n"); - return US_BULK_TRANSFER_FAILED; - } - - /* -ENOENT -- we canceled this transfer */ - if (result == -ENOENT) { - US_DEBUGP("scm_raw_bulk():" - " transfer aborted\n"); - return US_BULK_TRANSFER_ABORTED; - } - - if (result == -EPIPE) { - US_DEBUGP("scm_raw_bulk():" - " output pipe stalled\n"); - return USB_STOR_TRANSPORT_FAILED; - } - - /* the catch-all case */ - US_DEBUGP("us_transfer_partial(): unknown error\n"); - return US_BULK_TRANSFER_FAILED; - } - - if (act_len != len) { - US_DEBUGP("Warning: Transferred only %d bytes\n", - act_len); - return US_BULK_TRANSFER_SHORT; - } - - US_DEBUGP("Transfered %d of %d bytes\n", act_len, len); - - return US_BULK_TRANSFER_GOOD; -} - -/* - * Note: direction must be set if command_len == 0. - */ - -static int scm_bulk_transport(struct us_data *us, - unsigned char *command, - unsigned short command_len, - int direction, - unsigned char *data, - unsigned short len, - int use_sg) { - - int result = USB_STOR_TRANSPORT_GOOD; - int transferred = 0; - unsigned char execute[8] = { - 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - int i; - struct scatterlist *sg; - char string[64]; - - if (command_len != 0) { - - /* Fix up the command's data length */ - - command[6] = len&0xFF; - command[7] = (len>>8)&0xFF; - - result = scm_send_control(us, - execute, - command, - command_len); - - if (result != USB_STOR_TRANSPORT_GOOD) - return result; - } - - if (len==0) - return USB_STOR_TRANSPORT_GOOD; - - - /* transfer the data payload for the command, if there is any */ - - - if (command_len != 0) - direction = (command[0]&0x80) ? SCSI_DATA_READ : - SCSI_DATA_WRITE; - - if (direction == SCSI_DATA_WRITE) { - - /* Debug-print the first 48 bytes of the write transfer */ - - if (!use_sg) { - string[0] = 0; - for (i=0; i sg[i].length ? - sg[i].length : len-transferred); - if (result!=US_BULK_TRANSFER_GOOD) - break; - transferred += sg[i].length; - } - } - - return result; -} - -int scm_read(struct us_data *us, - unsigned char access, - unsigned char reg, - unsigned char *content) { - - int result; - unsigned char command[8] = { - 0xC0, access, reg, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - result = scm_send_control(us, command, content, 1); - - if (result != USB_STOR_TRANSPORT_GOOD) - return result; - - // US_DEBUGP("SCM: Reg %d -> %02X\n", reg, *content); - - return result; -} - -int scm_write(struct us_data *us, - unsigned char access, - unsigned char reg, - unsigned char content) { - - int result; - unsigned char command[8] = { - 0x40, access|0x01, reg, content, 0x00, 0x00, 0x00, 0x00 - }; - - result = scm_send_control(us, command, NULL, 0); - - if (result != USB_STOR_TRANSPORT_GOOD) - return result; - - // US_DEBUGP("SCM: Reg %d <- %02X\n", reg, content); - - return result; -} - -int scm_set_shuttle_features(struct us_data *us, - unsigned char external_trigger, - unsigned char epp_control, - unsigned char mask_byte, - unsigned char test_pattern, - unsigned char subcountH, - unsigned char subcountL) { - - int result; - unsigned char command[8] = { - 0x40, 0x81, epp_control, external_trigger, - test_pattern, mask_byte, subcountL, subcountH - }; - - result = scm_bulk_transport(us, command, 8, 0, NULL, 0, 0); - - if (result != USB_STOR_TRANSPORT_GOOD) - return result; - - return result; -} - -int scm_read_block(struct us_data *us, - unsigned char access, - unsigned char reg, - unsigned char *content, - unsigned short len, - int use_sg) { - - int result; - unsigned char command[8] = { - 0xC0, access|0x02, reg, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - result = scm_bulk_transport(us, - command, 8, 0, content, len, use_sg); - - if (result != USB_STOR_TRANSPORT_GOOD) - return result; - - // US_DEBUGP("SCM: Read data, result %d\n", result); - - return result; -} - -/* - * Block, waiting for an ATA device to become not busy or to report - * an error condition. - */ - -int scm_wait_not_busy(struct us_data *us) { - - int i; - int result; - unsigned char status; - - /* Synchronizing cache on a CDR could take a heck of a long time, - but probably not more than 15 minutes or so */ - - for (i=0; i<500; i++) { - result = scm_read(us, SCM_ATA, 0x17, &status); - US_DEBUGP("SCM: Write ATA data status is %02X\n", status); - if (result!=USB_STOR_TRANSPORT_GOOD) - return result; - if (status&0x01) // check condition - return USB_STOR_TRANSPORT_FAILED; - if (status&0x20) // device fault - return USB_STOR_TRANSPORT_FAILED; - if ((status&0x80)!=0x80) // not busy - break; - if (i<5) - wait_ms(100); - else if (i<20) - wait_ms(500); - else if (i<49) - wait_ms(1000); - else if (i<499) - wait_ms(2000); - } - - if (i==500) - return USB_STOR_TRANSPORT_FAILED; - - return USB_STOR_TRANSPORT_GOOD; -} - -int scm_write_block(struct us_data *us, - unsigned char access, - unsigned char reg, - unsigned char *content, - unsigned short len, - int use_sg) { - - int result; - unsigned char command[8] = { - 0x40, access|0x03, reg, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - result = scm_bulk_transport(us, - command, 8, 0, content, len, use_sg); - - if (result!=USB_STOR_TRANSPORT_GOOD) - return result; - - return scm_wait_not_busy(us); -} - -int scm_write_block_test(struct us_data *us, - unsigned char access, - unsigned char *registers, - unsigned char *data_out, - unsigned short num_registers, - unsigned char data_reg, - unsigned char status_reg, - unsigned char qualifier, - unsigned char timeout, - unsigned char *content, - unsigned short len, - int use_sg) { - - int result; - unsigned char command[16] = { - 0x40, access|0x07, 0x07, 0x17, 0xfc, 0xe7, 0x00, 0x00, - 0x40, access|0x05, data_reg, status_reg, - qualifier, timeout, 0x00, 0x00 - }; - int i; - unsigned char data[num_registers*2]; - int transferred; - struct scatterlist *sg; - char string[64]; - - command[14] = len&0xFF; - command[15] = (len>>8)&0xFF; - - for (i=0; i sg[i].length ? - sg[i].length : len-transferred); - if (result!=US_BULK_TRANSFER_GOOD) - break; - transferred += sg[i].length; - } - } - - if (result!=USB_STOR_TRANSPORT_GOOD) - return result; - - return scm_wait_not_busy(us); -} - -int scm_multiple_write(struct us_data *us, - unsigned char access, - unsigned char *registers, - unsigned char *data_out, - unsigned short num_registers) { - - int result; - unsigned char data[num_registers*2]; - int i; - unsigned char cmd[8] = { - 0x40, access|0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - for (i=0; i %02X\n", *data_flags); - - return result; -} - -int scm_write_user_io(struct us_data *us, - unsigned char enable_flags, - unsigned char data_flags) { - - unsigned char command[8] = { - 0x40, 0x82, enable_flags, data_flags, 0x00, 0x00, 0x00, 0x00 - }; - int result; - - result = scm_send_control(us, command, NULL, 0); - - if (result != USB_STOR_TRANSPORT_GOOD) - return result; - - // US_DEBUGP("SCM: User I/O flags <- %02X\n", data_flags); - - return result; -} - -static int init_sddr09(struct us_data *us) { - - int result; - unsigned char data[14]; - unsigned char command[8] = { - 0xc1, 0x01, 0, 0, 0, 0, 0, 0 - }; - unsigned char command2[8] = { - 0x41, 0, 0, 0, 0, 0, 0, 0 - }; - unsigned char tur[12] = { - 0x03, 0x20, 0, 0, 0x0e, 0, 0, 0, 0, 0, 0, 0 - }; - - if ( (result = scm_send_control(us, command, data, 2)) != - USB_STOR_TRANSPORT_GOOD) - return result; - - US_DEBUGP("SDDR09: %02X %02X\n", data[0], data[1]); - - command[1] = 0x08; - - if ( (result = scm_send_control(us, command, data, 2)) != - USB_STOR_TRANSPORT_GOOD) - return result; - - US_DEBUGP("SDDR09: %02X %02X\n", data[0], data[1]); -/* - if ( (result = scm_send_control(us, command2, tur, 12)) != - USB_STOR_TRANSPORT_GOOD) { - US_DEBUGP("SDDR09: request sense failed\n"); - return result; - } - - if ( (result = scm_raw_bulk( - us, SCSI_DATA_READ, data, 14)) != - USB_STOR_TRANSPORT_GOOD) { - US_DEBUGP("SDDR09: request sense bulk in failed\n"); - return result; - } - - US_DEBUGP("SDDR09: request sense worked\n"); -*/ - return result; -} - -static int init_8200e(struct us_data *us) { - - int result; - unsigned char status; - - // Enable peripheral control signals - - if ( (result = scm_write_user_io(us, - SCM_UIO_OE1 | SCM_UIO_OE0, - SCM_UIO_EPAD | SCM_UIO_1)) != USB_STOR_TRANSPORT_GOOD) - return result; - - wait_ms(2000); - - if ( (result = scm_read_user_io(us, &status)) != - USB_STOR_TRANSPORT_GOOD) - return result; - - if ( (result = scm_read_user_io(us, &status)) != - USB_STOR_TRANSPORT_GOOD) - return result; - - // Reset peripheral, enable periph control signals - // (bring reset signal up) - - if ( (result = scm_write_user_io(us, - SCM_UIO_DRVRST | SCM_UIO_OE1 | SCM_UIO_OE0, - SCM_UIO_EPAD | SCM_UIO_1)) != USB_STOR_TRANSPORT_GOOD) - return result; - - // Enable periph control signals - // (bring reset signal down) - - if ( (result = scm_write_user_io(us, - SCM_UIO_OE1 | SCM_UIO_OE0, - SCM_UIO_EPAD | SCM_UIO_1)) != USB_STOR_TRANSPORT_GOOD) - return result; - - wait_ms(250); - - // Write 0x80 to ISA port 0x3F - - if ( (result = scm_write(us, SCM_ISA, 0x3F, 0x80)) != - USB_STOR_TRANSPORT_GOOD) - return result; - - // Read ISA port 0x27 - - if ( (result = scm_read(us, SCM_ISA, 0x27, &status)) != - USB_STOR_TRANSPORT_GOOD) - return result; - - if ( (result = scm_read_user_io(us, &status)) != - USB_STOR_TRANSPORT_GOOD) - return result; - - if ( (result = hp_8200e_select_and_test_registers(us)) != - USB_STOR_TRANSPORT_GOOD) - return result; - - if ( (result = scm_read_user_io(us, &status)) != - USB_STOR_TRANSPORT_GOOD) - return result; - - // Enable periph control signals and card detect - - if ( (result = scm_write_user_io(us, - SCM_UIO_ACKD |SCM_UIO_OE1 | SCM_UIO_OE0, - SCM_UIO_EPAD | SCM_UIO_1)) != USB_STOR_TRANSPORT_GOOD) - return result; - - if ( (result = scm_read_user_io(us, &status)) != - USB_STOR_TRANSPORT_GOOD) - return result; - - wait_ms(1400); - - if ( (result = scm_read_user_io(us, &status)) != - USB_STOR_TRANSPORT_GOOD) - return result; - - if ( (result = hp_8200e_select_and_test_registers(us)) != - USB_STOR_TRANSPORT_GOOD) - return result; - - if ( (result = scm_set_shuttle_features(us, - 0x83, 0x00, 0x88, 0x08, 0x15, 0x14)) != - USB_STOR_TRANSPORT_GOOD) - return result; - - return result; -} - -/* - * Transport for the HP 8200e - */ -int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us) -{ - int result; - unsigned char status; - unsigned char registers[32]; - unsigned char data[32]; - unsigned int len; - int i; - char string[64]; - - /* This table tells us: - X = command not supported - L = return length in cmnd[4] (8 bits). - H = return length in cmnd[7] and cmnd[8] (16 bits). - D = return length in cmnd[6] to cmnd[9] (32 bits). - B = return length/blocksize in cmnd[6] to cmnd[8]. - T = return length in cmnd[6] to cmnd[8] (24 bits). - 0-9 = fixed return length - W = 24 bytes - h = return length/2048 in cmnd[7-8]. - */ - - static char *lengths = - - /* 0123456789ABCDEF 0123456789ABCDEF */ - - "0XXL0XXXXXXXXXXX" "XXLXXXXXXXX0XX0X" /* 00-1F */ - "XXXXX8XXhXH0XXX0" "XXXXX0XXXXXXXXXX" /* 20-3F */ - "XXHHL0X0XXH0XX0X" "XHH00HXX0TH0H0XX" /* 40-5F */ - "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 60-7F */ - "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 80-9F */ - "X0XXX0XXDXDXXXXX" "XXXXXXXXX000XHBX" /* A0-BF */ - "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* C0-DF */ - "XDXXXXXXXXXXXXXX" "XXW00HXXXXXXXXXX"; /* E0-FF */ - - if (us->flags & US_FL_NEED_INIT) { - US_DEBUGP("8200e: initializing\n"); - init_8200e(us); - us->flags &= ~US_FL_NEED_INIT; - } - - len = srb->request_bufflen; - -/* if (srb->sc_data_direction == SCSI_DATA_WRITE) - len = srb->request_bufflen; - else { - - switch (lengths[srb->cmnd[0]]) { - - case 'L': - len = srb->cmnd[4]; - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - len = lengths[srb->cmnd[0]]-'0'; - break; - case 'H': - len = (((unsigned int)srb->cmnd[7])<<8) | srb->cmnd[8]; - break; - case 'h': - len = (((unsigned int)srb->cmnd[7])<<8) | srb->cmnd[8]; - len <<= 11; // *2048 - break; - case 'T': - len = (((unsigned int)srb->cmnd[6])<<16) | - (((unsigned int)srb->cmnd[7])<<8) | - srb->cmnd[8]; - break; - case 'D': - len = (((unsigned int)srb->cmnd[6])<<24) | - (((unsigned int)srb->cmnd[7])<<16) | - (((unsigned int)srb->cmnd[8])<<8) | - srb->cmnd[9]; - break; - case 'W': - len = 24; - break; - case 'B': - // Let's try using the command structure's - // request_bufflen here - len = srb->request_bufflen; - break; - default: - US_DEBUGP("Error: UNSUPPORTED COMMAND %02X\n", - srb->cmnd[0]); - return USB_STOR_TRANSPORT_ERROR; - } - } */ - - if (len > 0xFFFF) { - US_DEBUGP("Error: len = %08X... what do I do now?\n", - len); - return USB_STOR_TRANSPORT_ERROR; - } - - // US_DEBUGP("XXXXXXXXXXXXXXXX req_bufflen %d, len %d, bufflen %d\n", - // srb->request_bufflen, len, srb->bufflen); - - /* Send A0 (ATA PACKET COMMAND). - Note: I guess we're never going to get any of the ATA - commands... just ATA Packet Commands. - */ - - registers[0] = 0x11; - registers[1] = 0x12; - registers[2] = 0x13; - registers[3] = 0x14; - registers[4] = 0x15; - registers[5] = 0x16; - registers[6] = 0x17; - data[0] = 0x00; - data[1] = 0x00; - data[2] = 0x00; - data[3] = len&0xFF; // (cylL) = expected length (L) - data[4] = (len>>8)&0xFF; // (cylH) = expected length (H) - data[5] = 0xB0; // (device sel) = slave - data[6] = 0xA0; // (command) = ATA PACKET COMMAND - - if (srb->sc_data_direction == SCSI_DATA_WRITE) { - - for (i=7; i<19; i++) { - registers[i] = 0x10; - data[i] = (i-7 >= srb->cmd_len) ? 0 : srb->cmnd[i-7]; - } - - result = scm_write_block_test(us, SCM_ATA, - registers, data, 19, - 0x10, 0x17, 0xFD, 0x30, - srb->request_buffer, - len, srb->use_sg); - - return result; - } - - if ( (result = scm_multiple_write(us, - SCM_ATA, - registers, data, 7)) != USB_STOR_TRANSPORT_GOOD) { - return result; - } - - // Write the 12-byte command header. - - if ( (result = scm_write_block(us, - SCM_ATA, 0x10, srb->cmnd, 12, 0)) != - USB_STOR_TRANSPORT_GOOD) { - return result; - } - - // If there is response data to be read in - // then do it here. - - if (len != 0 && (srb->sc_data_direction == SCSI_DATA_READ)) { - - // How many bytes to read in? Check cylL register - - if ( (result = scm_read(us, SCM_ATA, 0x14, &status)) != - USB_STOR_TRANSPORT_GOOD) { - return result; - } - - if (len>0xFF) { // need to read cylH also - len = status; - if ( (result = scm_read(us, SCM_ATA, 0x15, &status)) != - USB_STOR_TRANSPORT_GOOD) { - return result; - } - len += ((unsigned int)status)<<8; - } - else - len = status; - - - result = scm_read_block(us, SCM_ATA, 0x10, - srb->request_buffer, len, srb->use_sg); - - /* Debug-print the first 32 bytes of the transfer */ - - if (!srb->use_sg) { - string[0] = 0; - for (i=0; irequest_buffer)[i]); - if ((i%16)==15) { - US_DEBUGP("%s\n", string); - string[0] = 0; - } - } - if (string[0]!=0) - US_DEBUGP("%s\n", string); - } - } - - // US_DEBUGP("Command result %d\n", result); - - return result; -} - - -/* - * Transport for the Sandisk SDDR-09 - */ -int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us) -{ - int result; - unsigned int len; - unsigned char send_scsi_command[8] = { - 0x41, 0, 0, 0, 0, 0, 0, 0 - }; - int i; - char string[64]; - unsigned char *ptr; - unsigned char inquiry_response[36] = { - 0x00, 0x80, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x00, - 'S', 'a', 'n', 'D', 'i', 's', 'k', ' ', - 'I', 'm', 'a', 'g', 'e', 'M', 'a', 't', - 'e', ' ', 'S', 'D', 'D', 'R', '0', '9', - ' ', ' ', ' ', ' ' - }; - - /* This table tells us: - X = command not supported - L = return length in cmnd[4] (8 bits). - H = return length in cmnd[7] and cmnd[8] (16 bits). - D = return length in cmnd[6] to cmnd[9] (32 bits). - B = return length/blocksize in cmnd[6] to cmnd[8]. - T = return length in cmnd[6] to cmnd[8] (24 bits). - 0-9 = fixed return length - W = 24 bytes - h = return length/2048 in cmnd[7-8]. - */ - - static char *lengths = - - /* 0123456789ABCDEF 0123456789ABCDEF */ - - "0XXL0XXXXXXXXXXX" "XXLXXXXXXXX0XX0X" /* 00-1F */ - "XXXXX8XXhXH0XXX0" "XXXXX0XXXXXXXXXX" /* 20-3F */ - "XXHHL0X0XXH0XX0X" "XHH00HXX0TH0H0XX" /* 40-5F */ - "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 60-7F */ - "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 80-9F */ - "X0XXX0XXDXDXXXXX" "XXXXXXXXX000XHBX" /* A0-BF */ - "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* C0-DF */ - "XDXXXXXXXXXXXXXX" "XXW00HXXXXXXXXXX"; /* E0-FF */ - - if (us->flags & US_FL_NEED_INIT) { - US_DEBUGP("SDDR-09: initializing\n"); - init_sddr09(us); - us->flags &= ~US_FL_NEED_INIT; - } - - /* if (srb->sc_data_direction == SCSI_DATA_WRITE) */ - len = srb->request_bufflen; - /* else { - - switch (lengths[srb->cmnd[0]]) { - - case 'L': - len = srb->cmnd[4]; - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - len = lengths[srb->cmnd[0]]-'0'; - break; - case 'H': - len = (((unsigned int)srb->cmnd[7])<<8) | srb->cmnd[8]; - break; - case 'h': - len = (((unsigned int)srb->cmnd[7])<<8) | srb->cmnd[8]; - len <<= 11; // *2048 - break; - case 'T': - len = (((unsigned int)srb->cmnd[6])<<16) | - (((unsigned int)srb->cmnd[7])<<8) | - srb->cmnd[8]; - break; - case 'D': - len = (((unsigned int)srb->cmnd[6])<<24) | - (((unsigned int)srb->cmnd[7])<<16) | - (((unsigned int)srb->cmnd[8])<<8) | - srb->cmnd[9]; - break; - case 'W': - len = 24; - break; - case 'B': - // Let's try using the command structure's - // request_bufflen here - len = srb->request_bufflen; - break; - default: - US_DEBUGP("Error: UNSUPPORTED COMMAND %02X\n", - srb->cmnd[0]); - return USB_STOR_TRANSPORT_ERROR; - } - } */ - - if (srb->request_bufflen > 0xFFFF) { - US_DEBUGP("Error: len = %08X... what do I do now?\n", - len); - return USB_STOR_TRANSPORT_ERROR; - } - - /* Dummy up a response for INQUIRY since SDDR09 doesn't - respond to INQUIRY commands */ - - if (srb->cmnd[0] == INQUIRY) { - memcpy(srb->request_buffer, inquiry_response, 36); - return USB_STOR_TRANSPORT_GOOD; - } - - for (; srb->cmd_len<12; srb->cmd_len++) - srb->cmnd[srb->cmd_len] = 0; - - srb->cmnd[1] = 0x20; - - string[0] = 0; - for (i=0; i<12; i++) - sprintf(string+strlen(string), "%02X ", srb->cmnd[i]); - - US_DEBUGP("SDDR09: Send control for command %s\n", - string); - - if ( (result = scm_send_control(us, send_scsi_command, - srb->cmnd, 12)) != USB_STOR_TRANSPORT_GOOD) - return result; - - US_DEBUGP("SDDR09: Control for command OK\n"); - - if (srb->sc_data_direction == SCSI_DATA_WRITE || - srb->sc_data_direction == SCSI_DATA_READ) { - - US_DEBUGP("SDDR09: %s %d bytes\n", - srb->sc_data_direction==SCSI_DATA_WRITE ? - "sending" : "receiving", - len); - - result = scm_bulk_transport(us, - NULL, 0, srb->sc_data_direction, - srb->request_buffer, - len, srb->use_sg); - - return result; - - } - - return result; -} - diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/storage/scm.h linux/drivers/usb/storage/scm.h --- v2.4.0-test5/linux/drivers/usb/storage/scm.h Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/storage/scm.h Wed Dec 31 16:00:00 1969 @@ -1,82 +0,0 @@ -/* Driver for SCM Microsystems USB-ATAPI cable - * Header File - * - * $Id: scm.h,v 1.3 2000/07/24 19:19:52 mdharm Exp $ - * - * Current development and maintainance by: - * (c) 2000 Robert Baruch (autophile@dol.net) - * - * See scm.c for more explanation - * - * 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, 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. - */ - -#ifndef _USB_SCM_H -#define _USB_SCM_H - -#define SCM_EPP_PORT 0x10 -#define SCM_EPP_REGISTER 0x30 -#define SCM_ATA 0x40 -#define SCM_ISA 0x50 - -/* SCM User I/O Data registers */ - -#define SCM_UIO_EPAD 0x80 // Enable Peripheral Control Signals -#define SCM_UIO_CDT 0x40 // Card Detect (Read Only) - // CDT = ACKD & !UI1 & !UI0 -#define SCM_UIO_1 0x20 // I/O 1 -#define SCM_UIO_0 0x10 // I/O 0 -#define SCM_UIO_EPP_ATA 0x08 // 1=EPP mode, 0=ATA mode -#define SCM_UIO_UI1 0x04 // Input 1 -#define SCM_UIO_UI0 0x02 // Input 0 -#define SCM_UIO_INTR_ACK 0x01 // Interrupt (ATA & ISA)/Acknowledge (EPP) - -/* SCM User I/O Enable registers */ - -#define SCM_UIO_DRVRST 0x80 // Reset Peripheral -#define SCM_UIO_ACKD 0x40 // Enable Card Detect -#define SCM_UIO_OE1 0x20 // I/O 1 set=output/clr=input - // If ACKD=1, set OE1 to 1 also. -#define SCM_UIO_OE0 0x10 // I/O 0 set=output/clr=input -#define SCM_UIO_ADPRST 0x01 // Reset SCM chip - -/* SCM-specific commands */ - -extern int scm_read(struct us_data *us, unsigned char access, - unsigned char reg, unsigned char *content); -extern int scm_write(struct us_data *us, unsigned char access, - unsigned char reg, unsigned char content); -extern int scm_read_block(struct us_data *us, unsigned char access, - unsigned char reg, unsigned char *content, unsigned short len, - int use_sg); -extern int scm_write_block(struct us_data *us, unsigned char access, - unsigned char reg, unsigned char *content, unsigned short len, - int use_sg); -extern int scm_multiple_write(struct us_data *us, unsigned char access, - unsigned char *registers, unsigned char *data_out, - unsigned short num_registers); -extern int scm_read_user_io(struct us_data *us, unsigned char *data_flags); -extern int scm_write_user_io(struct us_data *us, - unsigned char enable_flags, unsigned char data_flags); - -/* HP 8200e stuff */ - -extern int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us); - -/* Sandisk SDDR-09 stuff */ - -extern int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us); - -#endif diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/storage/scsiglue.c linux/drivers/usb/storage/scsiglue.c --- v2.4.0-test5/linux/drivers/usb/storage/scsiglue.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/storage/scsiglue.c Tue Aug 1 18:54:58 2000 @@ -1,13 +1,14 @@ /* Driver for USB Mass Storage compliant devices * SCSI layer glue code * - * $Id: scsiglue.c,v 1.5 2000/07/24 18:55:39 mdharm Exp $ + * $Id: scsiglue.c,v 1.7 2000/07/28 20:33:18 gowdy Exp $ * * Current development and maintainance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) * * Developed with the assistance of: * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org) + * (c) 2000 Stephen J. Gowdy (SGowdy@lbl.gov) * * Initial work by: * (c) 1999 Michael Gee (michael@linuxspecific.com) @@ -48,21 +49,6 @@ #include "debug.h" #include - -/* direction table -- this indicates the direction of the data - * transfer for each command code -- a 1 indicates input - */ -/* FIXME: we need to use the new direction indicators in the Scsi_Cmnd - * structure, not this table. First we need to evaluate if it's being set - * correctly for us, though - */ -unsigned char us_direction[256/8] = { - 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77, - 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - /* * kernel thread actions diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/storage/scsiglue.h linux/drivers/usb/storage/scsiglue.h --- v2.4.0-test5/linux/drivers/usb/storage/scsiglue.h Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/storage/scsiglue.h Mon Jul 31 10:34:27 2000 @@ -1,7 +1,7 @@ /* Driver for USB Mass Storage compliant devices * SCSI Connecting Glue Header File * - * $Id: scsiglue.h,v 1.2 2000/07/19 22:12:07 mdharm Exp $ + * $Id: scsiglue.h,v 1.3 2000/07/25 23:04:47 mdharm Exp $ * * Current development and maintainance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -46,7 +46,6 @@ #include "hosts.h" extern unsigned char usb_stor_sense_notready[18]; -extern unsigned char us_direction[256/8]; extern Scsi_Host_Template usb_stor_host_template; extern int usb_stor_scsiSense10to6(Scsi_Cmnd*); extern int usb_stor_scsiSense6to10(Scsi_Cmnd*); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/storage/sddr09.c linux/drivers/usb/storage/sddr09.c --- v2.4.0-test5/linux/drivers/usb/storage/sddr09.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/storage/sddr09.c Tue Aug 1 18:54:58 2000 @@ -0,0 +1,925 @@ +/* Driver for SanDisk SDDR-09 SmartMedia reader + * + * SDDR09 driver v0.1: + * + * First release + * + * Current development and maintainance by: + * (c) 2000 Robert Baruch (autophile@dol.net) + * + * The SanDisk SDDR-09 SmartMedia reader uses the Shuttle EUSB-01 chip. + * This chip is a programmable USB controller. In the SDDR-09, it has + * been programmed to obey a certain limited set of SCSI commands. This + * driver translates the "real" SCSI commands to the SDDR-09 SCSI + * commands. + * + * 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, 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. + */ + +#include "transport.h" +#include "protocol.h" +#include "usb.h" +#include "debug.h" +#include "sddr09.h" + +#include +#include +#include + +extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe, + u8 request, u8 requesttype, u16 value, u16 index, + void *data, u16 size); +extern int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe, + unsigned int len, unsigned int *act_len); + +#define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) ) +#define LSB_of(s) ((s)&0xFF) +#define MSB_of(s) ((s)>>8) + +/* + * Send a control message and wait for the response. + * + * us - the pointer to the us_data structure for the device to use + * + * request - the URB Setup Packet's first 6 bytes. The first byte always + * corresponds to the request type, and the second byte always corresponds + * to the request. The other 4 bytes do not correspond to value and index, + * since they are used in a custom way by the SCM protocol. + * + * xfer_data - a buffer from which to get, or to which to store, any data + * that gets send or received, respectively, with the URB. Even though + * it looks like we allocate a buffer in this code for the data, xfer_data + * must contain enough allocated space. + * + * xfer_len - the number of bytes to send or receive with the URB. + * + */ + +static int sddr09_send_control(struct us_data *us, + int pipe, + unsigned char request, + unsigned char requesttype, + unsigned short value, + unsigned short index, + unsigned char *xfer_data, + unsigned int xfer_len) { + + int result; + + // If data is going to be sent or received with the URB, + // then allocate a buffer for it. If data is to be sent, + // copy the data into the buffer. +/* + if (xfer_len > 0) { + buffer = kmalloc(xfer_len, GFP_KERNEL); + if (!(command[0] & USB_DIR_IN)) + memcpy(buffer, xfer_data, xfer_len); + } +*/ + // Send the URB to the device and wait for a response. + + /* Why are request and request type reversed in this call? */ + + result = usb_stor_control_msg(us, pipe, + request, requesttype, value, index, + xfer_data, xfer_len); + + + // If data was sent or received with the URB, free the buffer we + // allocated earlier, but not before reading the data out of the + // buffer if we wanted to receive data. +/* + if (xfer_len > 0) { + if (command[0] & USB_DIR_IN) + memcpy(xfer_data, buffer, xfer_len); + kfree(buffer); + } +*/ + // Check the return code for the command. + + if (result < 0) { + /* if the command was aborted, indicate that */ + if (result == -ENOENT) + return USB_STOR_TRANSPORT_ABORTED; + + /* a stall is a fatal condition from the device */ + if (result == -EPIPE) { + US_DEBUGP("-- Stall on control pipe. Clearing\n"); + result = usb_clear_halt(us->pusb_dev, pipe); + US_DEBUGP("-- usb_clear_halt() returns %d\n", result); + return USB_STOR_TRANSPORT_FAILED; + } + + /* Uh oh... serious problem here */ + return USB_STOR_TRANSPORT_ERROR; + } + + return USB_STOR_TRANSPORT_GOOD; +} + +static int sddr09_raw_bulk(struct us_data *us, + int direction, + unsigned char *data, + unsigned int len) { + + int result; + int act_len; + int pipe; + + if (direction == SCSI_DATA_READ) + pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); + else + pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out); + + result = usb_stor_bulk_msg(us, data, pipe, len, &act_len); + + /* if we stall, we need to clear it before we go on */ + if (result == -EPIPE) { + US_DEBUGP("EPIPE: clearing endpoint halt for" + " pipe 0x%x, stalled at %d bytes\n", + pipe, act_len); + usb_clear_halt(us->pusb_dev, pipe); + } + + if (result) { + + /* NAK - that means we've retried a few times already */ + if (result == -ETIMEDOUT) { + US_DEBUGP("usbat_raw_bulk():" + " device NAKed\n"); + return US_BULK_TRANSFER_FAILED; + } + + /* -ENOENT -- we canceled this transfer */ + if (result == -ENOENT) { + US_DEBUGP("usbat_raw_bulk():" + " transfer aborted\n"); + return US_BULK_TRANSFER_ABORTED; + } + + if (result == -EPIPE) { + US_DEBUGP("usbat_raw_bulk():" + " output pipe stalled\n"); + return USB_STOR_TRANSPORT_FAILED; + } + + /* the catch-all case */ + US_DEBUGP("us_transfer_partial(): unknown error\n"); + return US_BULK_TRANSFER_FAILED; + } + + if (act_len != len) { + US_DEBUGP("Warning: Transferred only %d bytes\n", + act_len); + return US_BULK_TRANSFER_SHORT; + } + + US_DEBUGP("Transfered %d of %d bytes\n", act_len, len); + + return US_BULK_TRANSFER_GOOD; +} + +/* + * Note: direction must be set if command_len == 0. + */ + +static int sddr09_bulk_transport(struct us_data *us, + int direction, + unsigned char *data, + unsigned int len, + int use_sg) { + + int result = USB_STOR_TRANSPORT_GOOD; + int transferred = 0; + int i; + struct scatterlist *sg; + char string[64]; + + if (len==0) + return USB_STOR_TRANSPORT_GOOD; + + + /* transfer the data */ + + if (direction == SCSI_DATA_WRITE) { + + /* Debug-print the first 48 bytes of the write transfer */ + + if (!use_sg) { + strcpy(string, "wr: "); + for (i=0; i sg[i].length ? + sg[i].length : len-transferred); + if (result!=US_BULK_TRANSFER_GOOD) + break; + transferred += sg[i].length; + } + } + + if (direction == SCSI_DATA_READ) { + + /* Debug-print the first 48 bytes of the read transfer */ + + if (!use_sg) { + strcpy(string, "rd: "); + for (i=0; iextra; + unsigned int lba; + unsigned int pba; + unsigned short page; + unsigned short pages; + unsigned char *buffer = NULL; + unsigned char *ptr; + struct scatterlist *sg = NULL; + int i; + int len; + int transferred; + + // If we're using scatter-gather, we have to create a new + // buffer to read all of the data in first, since a + // scatter-gather buffer could in theory start in the middle + // of a page, which would be bad. A developer who wants a + // challenge might want to write a limited-buffer + // version of this code. + + len = sectors*info->pagesize; + + if (use_sg) { + sg = (struct scatterlist *)content; + buffer = kmalloc(len, GFP_KERNEL); + if (buffer == NULL) + return USB_STOR_TRANSPORT_ERROR; + ptr = buffer; + } else + ptr = content; + + // Figure out the initial LBA and page + + pba = (address/info->pagesize)>>4; + lba = info->pba_to_lba[pba]; + page = (address/info->pagesize)&0x0F; + + // This could be made much more efficient by checking for + // contiguous LBA's. Another exercise left to the student. + + while (sectors>0) { + + pba = info->lba_to_pba[lba]; + + // Read as many sectors as possible in this block + + pages = 0x10-page; + if (pages > sectors) + pages = sectors; + + US_DEBUGP("Read %01X pages, from PBA %04X" + " (LBA %04X) page %01X\n", + pages, pba, lba, page); + + address = ((pba<<4)+page)*info->pagesize; + + // Unlike in the documentation, the address is in + // words of 2 bytes. + + command[2] = MSB_of(address>>17); + command[3] = LSB_of(address>>17); + command[4] = MSB_of((address>>1)&0xFFFF); + command[5] = LSB_of((address>>1)&0xFFFF); + + command[10] = MSB_of(pages); + command[11] = LSB_of(pages); + + result = sddr09_send_control(us, + usb_sndctrlpipe(us->pusb_dev,0), + 0, + 0x41, + 0, + 0, + command, + 12); + + US_DEBUGP("Result for send_control in read_data %d\n", + result); + + if (result != USB_STOR_TRANSPORT_GOOD) { + if (use_sg) + kfree(buffer); + return result; + } + + result = sddr09_bulk_transport(us, + SCSI_DATA_READ, ptr, + pages*info->pagesize, 0); + + if (result != USB_STOR_TRANSPORT_GOOD) { + if (use_sg) + kfree(buffer); + return result; + } + + page = 0; + lba++; + sectors -= pages; + ptr += pages*info->pagesize; + } + + if (use_sg) { + transferred = 0; + for (i=0; i sg[i].length ? + sg[i].length : len-transferred); + transferred += sg[i].length; + } + kfree(buffer); + } + + return USB_STOR_TRANSPORT_GOOD; +} + +int sddr09_read_control(struct us_data *us, + unsigned long address, + unsigned short blocks, + unsigned char *content, + int use_sg) { + + // Unlike in the documentation, the last two bytes are the + // number of blocks, not sectors. + + int result; + unsigned char command[12] = { + 0xe8, 0x21, MSB_of(address>>16), + LSB_of(address>>16), MSB_of(address&0xFFFF), + LSB_of(address&0xFFFF), 0, 0, 0, 0, + MSB_of(blocks), LSB_of(blocks) + }; + + US_DEBUGP("Read control address %08X blocks %04X\n", + address, blocks); + + result = sddr09_send_control(us, + usb_sndctrlpipe(us->pusb_dev,0), + 0, + 0x41, + 0, + 0, + command, + 12); + + US_DEBUGP("Result for send_control in read_control %d\n", + result); + + if (result != USB_STOR_TRANSPORT_GOOD) + return result; + + result = sddr09_bulk_transport(us, + SCSI_DATA_READ, content, + blocks*0x40, use_sg); + + US_DEBUGP("Result for bulk read in read_control %d\n", + result); + + return result; +} + +int sddr09_read_deviceID(struct us_data *us, + unsigned char *manufacturerID, + unsigned char *deviceID) { + + int result; + unsigned char command[12] = { + 0xed, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + unsigned char content[64]; + + result = sddr09_send_control(us, + usb_sndctrlpipe(us->pusb_dev,0), + 0, + 0x41, + 0, + 0, + command, + 12); + + US_DEBUGP("Result of send_control for device ID is %d\n", + result); + + if (result != USB_STOR_TRANSPORT_GOOD) + return result; + + result = sddr09_bulk_transport(us, + SCSI_DATA_READ, content, + 64, 0); + + *manufacturerID = content[0]; + *deviceID = content[1]; + + return result; +} + +int sddr09_read_status(struct us_data *us, + unsigned char *status) { + + int result; + unsigned char command[12] = { + 0xec, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + result = sddr09_send_control(us, + usb_sndctrlpipe(us->pusb_dev,0), + 0, + 0x41, + 0, + 0, + command, + 12); + + if (result != USB_STOR_TRANSPORT_GOOD) + return result; + + result = sddr09_bulk_transport(us, + SCSI_DATA_READ, status, + 1, 0); + + return result; +} + +int sddr09_reset(struct us_data *us) { + + int result; + unsigned char command[12] = { + 0xeb, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + result = sddr09_send_control(us, + usb_sndctrlpipe(us->pusb_dev,0), + 0, + 0x41, + 0, + 0, + command, + 12); + + return result; +} + +unsigned long sddr09_get_capacity(struct us_data *us, + unsigned int *pagesize) { + + unsigned char manufacturerID; + unsigned char deviceID; + int result; + + US_DEBUGP("Reading capacity...\n"); + + result = sddr09_read_deviceID(us, + &manufacturerID, + &deviceID); + + US_DEBUGP("Result of read_deviceID is %d\n", + result); + + if (result != USB_STOR_TRANSPORT_GOOD) + return 0; + + US_DEBUGP("Device ID = %02X\n", deviceID); + US_DEBUGP("Manuf ID = %02X\n", manufacturerID); + + *pagesize = 512; + + switch (deviceID) { + + case 0x6e: // 1MB + case 0xe8: + case 0xec: + *pagesize = 256; + return 0x00100000; + + case 0x5d: // 2MB + case 0xea: + case 0x64: + if (deviceID!=0x5D) + *pagesize = 256; + return 0x00200000; + + case 0xe3: // 4MB + case 0xe5: + case 0x6b: + case 0xd5: + return 0x00400000; + + case 0xe6: // 8MB + case 0xd6: + return 0x00800000; + + case 0x73: // 16MB + return 0x01000000; + + case 0x75: // 32MB + return 0x02000000; + + default: // unknown + return 0; + + } +} + +int sddr09_read_map(struct us_data *us) { + + unsigned char *control; + struct sddr09_card_info *info = (struct sddr09_card_info *)(us->extra); + int numblocks; + int i; + unsigned char *ptr; + unsigned short lba; + unsigned char parity; + unsigned char fast_parity[16] = { + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0 + }; + int result; + + if (!info->capacity) + return -1; + + /* read 64 (2^6) bytes for every block (8192 (2^13) bytes) + of capacity: + 64*(capacity/8192) = capacity*(2^6)*(2^-13) = + capacity*2^(6-13) = capacity*(2^-7) + */ + + control = kmalloc(info->capacity>>7, GFP_KERNEL); + + + numblocks = info->capacity>>13; + + if ( (result = sddr09_read_control(us, 0, numblocks, + control, 0)) != + USB_STOR_TRANSPORT_GOOD) { + kfree(control); + return -1; + } + + + + if (info->lba_to_pba) + kfree(info->lba_to_pba); + if (info->pba_to_lba) + kfree(info->pba_to_lba); + info->lba_to_pba = kmalloc(numblocks*sizeof(int), GFP_KERNEL); + info->pba_to_lba = kmalloc(numblocks*sizeof(int), GFP_KERNEL); + memset(info->lba_to_pba, 0, numblocks*sizeof(int)); + memset(info->pba_to_lba, 0, numblocks*sizeof(int)); + + for (i=0; i>4)!=0x01) + continue; + + /* ensure even parity */ + + lba = short_pack(ptr[7], ptr[6]); + parity = 1; // the parity of 0x1000 + parity ^= fast_parity[lba & 0x000F]; + parity ^= fast_parity[(lba>>4) & 0x000F]; + parity ^= fast_parity[(lba>>8) & 0x000F]; + + if (parity) { /* bad parity bit */ + US_DEBUGP("Bad parity in LBA for block %04X\n", i); + continue; + } + + lba = (lba&0x07FF)>>1; + + if (lba>=numblocks) { + US_DEBUGP("Bad LBA %04X for block %04X\n", lba, i); + continue; + } + + if (i<0x10) + US_DEBUGP("LBA %04X <-> PBA %04X\n", + lba, i); + + info->pba_to_lba[i] = lba; + info->lba_to_pba[lba] = i; + } + + kfree(control); + return 0; +} + +/* +static int init_sddr09(struct us_data *us) { + + int result; + unsigned char data[14]; + unsigned char command[8] = { + 0xc1, 0x01, 0, 0, 0, 0, 0, 0 + }; + unsigned char command2[8] = { + 0x41, 0, 0, 0, 0, 0, 0, 0 + }; + unsigned char tur[12] = { + 0x03, 0x20, 0, 0, 0x0e, 0, 0, 0, 0, 0, 0, 0 + }; + + if ( (result = sddr09_send_control(us, command, data, 2)) != + USB_STOR_TRANSPORT_GOOD) + return result; + + US_DEBUGP("SDDR09: %02X %02X\n", data[0], data[1]); + + command[1] = 0x08; + + if ( (result = sddr09_send_control(us, command, data, 2)) != + USB_STOR_TRANSPORT_GOOD) + return result; + + US_DEBUGP("SDDR09: %02X %02X\n", data[0], data[1]); + + if ( (result = sddr09_send_control(us, command2, tur, 12)) != + USB_STOR_TRANSPORT_GOOD) { + US_DEBUGP("SDDR09: request sense failed\n"); + return result; + } + + if ( (result = sddr09_raw_bulk( + us, SCSI_DATA_READ, data, 14)) != + USB_STOR_TRANSPORT_GOOD) { + US_DEBUGP("SDDR09: request sense bulk in failed\n"); + return result; + } + + US_DEBUGP("SDDR09: request sense worked\n"); + + return result; +} +*/ + +void sddr09_card_info_destructor(void *extra) { + struct sddr09_card_info *info = (struct sddr09_card_info *)extra; + + if (!extra) + return; + + if (info->lba_to_pba) + kfree(info->lba_to_pba); + if (info->pba_to_lba) + kfree(info->pba_to_lba); +} + +/* + * Transport for the Sandisk SDDR-09 + */ +int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us) +{ + int result; + int i; + char string[64]; + unsigned char inquiry_response[36] = { + 0x00, 0x80, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x00, + 'S', 'a', 'n', 'D', 'i', 's', 'k', ' ', + 'I', 'm', 'a', 'g', 'e', 'M', 'a', 't', + 'e', ' ', 'S', 'D', 'D', 'R', '0', '9', + ' ', ' ', ' ', ' ' + }; + unsigned char mode_page_01[12] = { + 0x01, 0x0a, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + unsigned char *ptr; + unsigned long capacity; + unsigned int lba; + unsigned int pba; + unsigned int page; + unsigned short pages; + struct sddr09_card_info *info = (struct sddr09_card_info *)(us->extra); + +/* + if (us->flags & US_FL_NEED_INIT) { + US_DEBUGP("SDDR-09: initializing\n"); + init_sddr09(us); + us->flags &= ~US_FL_NEED_INIT; + } +*/ + + if (!us->extra) { + us->extra = kmalloc( + sizeof(struct sddr09_card_info), GFP_KERNEL); + memset(us->extra, 0, sizeof(struct sddr09_card_info)); + us->extra_destructor = sddr09_card_info_destructor; + } + + ptr = (unsigned char *)srb->request_buffer; + + /* Dummy up a response for INQUIRY since SDDR09 doesn't + respond to INQUIRY commands */ + + if (srb->cmnd[0] == INQUIRY) { + memcpy(ptr, inquiry_response, 36); + return USB_STOR_TRANSPORT_GOOD; + } + + if (srb->cmnd[0] == READ_CAPACITY) { + + capacity = sddr09_get_capacity(us, &info->pagesize); + info->capacity = capacity; + + // Last page in the card + + capacity /= info->pagesize; + capacity--; + + ptr[0] = MSB_of(capacity>>16); + ptr[1] = LSB_of(capacity>>16); + ptr[2] = MSB_of(capacity&0xFFFF); + ptr[3] = LSB_of(capacity&0xFFFF); + + // The page size + + ptr[4] = MSB_of(info->pagesize>>16); + ptr[5] = LSB_of(info->pagesize>>16); + ptr[6] = MSB_of(info->pagesize&0xFFFF); + ptr[7] = LSB_of(info->pagesize&0xFFFF); + + sddr09_read_map(us); + + return USB_STOR_TRANSPORT_GOOD; + } + + if (srb->cmnd[0] == MODE_SENSE) { + + // Read-write error recovery page: there needs to + // be a check for write-protect here + + if ( (srb->cmnd[2] & 0x3F) == 0x01 ) { + if (ptr==NULL || srb->request_bufflen<12) + return USB_STOR_TRANSPORT_ERROR; + memcpy(ptr, mode_page_01, 12); + return USB_STOR_TRANSPORT_GOOD; + } + + // FIXME: sense buffer? + + return USB_STOR_TRANSPORT_ERROR; + } + + if (srb->cmnd[0] == READ_10) { + + page = short_pack(srb->cmnd[3], srb->cmnd[2]); + page <<= 16; + page |= short_pack(srb->cmnd[5], srb->cmnd[4]); + pages = short_pack(srb->cmnd[8], srb->cmnd[7]); + + // convert page to block and page-within-block + + lba = page>>4; + page = page&0x0F; + + // locate physical block corresponding to logical block + + if (lba>=(info->capacity>>13)) { + + // FIXME: sense buffer? + + return USB_STOR_TRANSPORT_ERROR; + } + + pba = info->lba_to_pba[lba]; + + // if pba is 0, either it's really 0, in which case + // the pba-to-lba map for pba 0 will be the lba, + // or that lba doesn't exist. + + if (pba==0 && info->pba_to_lba[0] != lba) { + + // FIXME: sense buffer? + + return USB_STOR_TRANSPORT_ERROR; + } + + US_DEBUGP("READ_10: read block %04X (LBA %04X) page %01X" + " pages %d\n", + pba, lba, page, pages); + + return sddr09_read_data(us, + ((pba<<4)+page)*info->pagesize, pages, + ptr, srb->use_sg); + } + + // Pass TEST_UNIT_READY and REQUEST_SENSE through + + if (srb->cmnd[0] != TEST_UNIT_READY && + srb->cmnd[0] != REQUEST_SENSE) + return USB_STOR_TRANSPORT_ERROR; // FIXME: sense buffer? + + for (; srb->cmd_len<12; srb->cmd_len++) + srb->cmnd[srb->cmd_len] = 0; + + srb->cmnd[1] = 0x20; + + string[0] = 0; + for (i=0; i<12; i++) + sprintf(string+strlen(string), "%02X ", srb->cmnd[i]); + + US_DEBUGP("SDDR09: Send control for command %s\n", + string); + + if ( (result = sddr09_send_control(us, + usb_sndctrlpipe(us->pusb_dev,0), + 0, + 0x41, + 0, + 0, + srb->cmnd, + 12)) != USB_STOR_TRANSPORT_GOOD) + return result; + + US_DEBUGP("SDDR09: Control for command OK\n"); + + if (srb->request_bufflen == 0) + return USB_STOR_TRANSPORT_GOOD; + + if (srb->sc_data_direction == SCSI_DATA_WRITE || + srb->sc_data_direction == SCSI_DATA_READ) { + + US_DEBUGP("SDDR09: %s %d bytes\n", + srb->sc_data_direction==SCSI_DATA_WRITE ? + "sending" : "receiving", + srb->request_bufflen); + + result = sddr09_bulk_transport(us, + srb->sc_data_direction, + srb->request_buffer, + srb->request_bufflen, srb->use_sg); + + return result; + + } + + return USB_STOR_TRANSPORT_GOOD; +} + diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/storage/sddr09.h linux/drivers/usb/storage/sddr09.h --- v2.4.0-test5/linux/drivers/usb/storage/sddr09.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/storage/sddr09.h Tue Aug 1 18:54:58 2000 @@ -0,0 +1,38 @@ +/* Driver for SanDisk SDDR-09 SmartMedia reader + * Header File + * + * Current development and maintainance by: + * (c) 2000 Robert Baruch (autophile@dol.net) + * + * See sddr09.c for more explanation + * + * 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, 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. + */ + +#ifndef _USB_SHUTTLE_EUSB_SDDR09_H +#define _USB_SHUTTLE_EUSB_SDDR09_H + +/* Sandisk SDDR-09 stuff */ + +extern int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us); + +struct sddr09_card_info { + unsigned long capacity; /* Size of card in bytes */ + int pagesize; /* Size of page in bytes */ + int *lba_to_pba; /* logical to physical map */ + int *pba_to_lba; /* physical to logical map */ +}; + +#endif diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/storage/shuttle_usbat.c linux/drivers/usb/storage/shuttle_usbat.c --- v2.4.0-test5/linux/drivers/usb/storage/shuttle_usbat.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/storage/shuttle_usbat.c Mon Jul 31 10:34:27 2000 @@ -0,0 +1,1067 @@ +/* Driver for SCM Microsystems USB-ATAPI cable + * + * SCM driver v0.2: + * + * Removed any reference to maxlen for bulk transfers. + * Changed scm_bulk_transport to allow for transfers without commands. + * Changed hp8200e transport to use the request_bufflen field in the + * SCSI command for the length of the transfer, rather than calculating + * it ourselves based on the command. + * + * SCM driver v0.1: + * + * First release - hp8200e. + * + * Current development and maintainance by: + * (c) 2000 Robert Baruch (autophile@dol.net) + * + * Many originally ATAPI devices were slightly modified to meet the USB + * market by using some kind of translation from ATAPI to USB on the host, + * and the peripheral would translate from USB back to ATAPI. + * + * SCM Microsystems (www.scmmicro.com) makes a device, sold to OEM's only, + * which does the USB-to-ATAPI conversion. By obtaining the data sheet on + * their device under nondisclosure agreement, I have been able to write + * this driver for Linux. + * + * The chip used in the device can also be used for EPP and ISA translation + * as well. This driver is only guaranteed to work with the ATAPI + * translation. + * + * The only peripherals that I know of (as of 14 Jul 2000) that uses this + * device is the Hewlett-Packard 8200e CD-Writer Plus. + * + * 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, 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. + */ + +#include "transport.h" +#include "protocol.h" +#include "usb.h" +#include "debug.h" +#include "shuttle_usbat.h" + +#include +#include +#include + +extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe, + u8 request, u8 requesttype, u16 value, u16 index, + void *data, u16 size); +extern int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe, + unsigned int len, unsigned int *act_len); + +#define short_pack(b1,b2) ( ((u16)(b1)) | ( ((u16)(b2))<<8 ) ) +#define LSB_of(s) ((s)&0xFF) +#define MSB_of(s) ((s)>>8) + +/* + * Send a control message and wait for the response. + * + * us - the pointer to the us_data structure for the device to use + * + * request - the URB Setup Packet's first 6 bytes. The first byte always + * corresponds to the request type, and the second byte always corresponds + * to the request. The other 4 bytes do not correspond to value and index, + * since they are used in a custom way by the SCM protocol. + * + * xfer_data - a buffer from which to get, or to which to store, any data + * that gets send or received, respectively, with the URB. Even though + * it looks like we allocate a buffer in this code for the data, xfer_data + * must contain enough allocated space. + * + * xfer_len - the number of bytes to send or receive with the URB. + * + */ + +static int usbat_send_control(struct us_data *us, + int pipe, + unsigned char request, + unsigned char requesttype, + unsigned short value, + unsigned short index, + unsigned char *xfer_data, + unsigned int xfer_len) { + + int result; + + // If data is going to be sent or received with the URB, + // then allocate a buffer for it. If data is to be sent, + // copy the data into the buffer. +/* + if (xfer_len > 0) { + buffer = kmalloc(xfer_len, GFP_KERNEL); + if (!(command[0] & USB_DIR_IN)) + memcpy(buffer, xfer_data, xfer_len); + } +*/ + // Send the URB to the device and wait for a response. + + /* Why are request and request type reversed in this call? */ + + result = usb_stor_control_msg(us, pipe, + request, requesttype, value, index, + xfer_data, xfer_len); + + + // If data was sent or received with the URB, free the buffer we + // allocated earlier, but not before reading the data out of the + // buffer if we wanted to receive data. +/* + if (xfer_len > 0) { + if (command[0] & USB_DIR_IN) + memcpy(xfer_data, buffer, xfer_len); + kfree(buffer); + } +*/ + // Check the return code for the command. + + if (result < 0) { + /* if the command was aborted, indicate that */ + if (result == -ENOENT) + return USB_STOR_TRANSPORT_ABORTED; + + /* a stall is a fatal condition from the device */ + if (result == -EPIPE) { + US_DEBUGP("-- Stall on control pipe. Clearing\n"); + result = usb_clear_halt(us->pusb_dev, pipe); + US_DEBUGP("-- usb_clear_halt() returns %d\n", result); + return USB_STOR_TRANSPORT_FAILED; + } + + /* Uh oh... serious problem here */ + return USB_STOR_TRANSPORT_ERROR; + } + + return USB_STOR_TRANSPORT_GOOD; +} + +static int usbat_raw_bulk(struct us_data *us, + int direction, + unsigned char *data, + unsigned short len) { + + int result; + int act_len; + int pipe; + + if (direction == SCSI_DATA_READ) + pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); + else + pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out); + + result = usb_stor_bulk_msg(us, data, pipe, len, &act_len); + + /* if we stall, we need to clear it before we go on */ + if (result == -EPIPE) { + US_DEBUGP("EPIPE: clearing endpoint halt for" + " pipe 0x%x, stalled at %d bytes\n", + pipe, act_len); + usb_clear_halt(us->pusb_dev, pipe); + } + + if (result) { + + /* NAK - that means we've retried a few times already */ + if (result == -ETIMEDOUT) { + US_DEBUGP("usbat_raw_bulk():" + " device NAKed\n"); + return US_BULK_TRANSFER_FAILED; + } + + /* -ENOENT -- we canceled this transfer */ + if (result == -ENOENT) { + US_DEBUGP("usbat_raw_bulk():" + " transfer aborted\n"); + return US_BULK_TRANSFER_ABORTED; + } + + if (result == -EPIPE) { + US_DEBUGP("usbat_raw_bulk():" + " output pipe stalled\n"); + return USB_STOR_TRANSPORT_FAILED; + } + + /* the catch-all case */ + US_DEBUGP("us_transfer_partial(): unknown error\n"); + return US_BULK_TRANSFER_FAILED; + } + + if (act_len != len) { + US_DEBUGP("Warning: Transferred only %d bytes\n", + act_len); + return US_BULK_TRANSFER_SHORT; + } + + US_DEBUGP("Transfered %d of %d bytes\n", act_len, len); + + return US_BULK_TRANSFER_GOOD; +} + +/* + * Note: direction must be set if command_len == 0. + */ + +static int usbat_bulk_transport(struct us_data *us, + unsigned char *command, + unsigned short command_len, + int direction, + unsigned char *data, + unsigned short len, + int use_sg) { + + int result = USB_STOR_TRANSPORT_GOOD; + int transferred = 0; + unsigned char execute[8] = { + 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + int i; + struct scatterlist *sg; + char string[64]; + int pipe; + +/* + if (command_len != 0) { + + // Fix up the command's data length + + command[6] = len&0xFF; + command[7] = (len>>8)&0xFF; + + + + result = usbat_send_control(us, + execute, + command, + command_len); + + if (result != USB_STOR_TRANSPORT_GOOD) + return result; + } +*/ + if (len==0) + return USB_STOR_TRANSPORT_GOOD; + + + /* transfer the data payload for the command, if there is any */ + + + if (command_len != 0) + direction = (command[0]&0x80) ? SCSI_DATA_READ : + SCSI_DATA_WRITE; + + if (direction == SCSI_DATA_WRITE) { + + /* Debug-print the first 48 bytes of the write transfer */ + + if (!use_sg) { + string[0] = 0; + for (i=0; i sg[i].length ? + sg[i].length : len-transferred); + if (result!=US_BULK_TRANSFER_GOOD) + break; + transferred += sg[i].length; + } + } + + return result; +} + +int usbat_read(struct us_data *us, + unsigned char access, + unsigned char reg, + unsigned char *content) { + + int result; + unsigned char command[8] = { + 0xC0, access, reg, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + result = usbat_send_control(us, + usb_rcvctrlpipe(us->pusb_dev,0), + access, + 0xC0, + (u16)reg, + 0, + content, + 1); + + // result = usbat_send_control(us, command, content, 1); + + return result; +} + +int usbat_write(struct us_data *us, + unsigned char access, + unsigned char reg, + unsigned char content) { + + int result; + unsigned char command[8] = { + 0x40, access|0x01, reg, content, 0x00, 0x00, 0x00, 0x00 + }; + + result = usbat_send_control(us, + usb_sndctrlpipe(us->pusb_dev,0), + access|0x01, + 0x40, + short_pack(reg, content), + 0, + NULL, + 0); + + // result = usbat_send_control(us, command, NULL, 0); + + return result; +} + +int usbat_set_shuttle_features(struct us_data *us, + unsigned char external_trigger, + unsigned char epp_control, + unsigned char mask_byte, + unsigned char test_pattern, + unsigned char subcountH, + unsigned char subcountL) { + + int result; + unsigned char command[8] = { + 0x40, 0x81, epp_control, external_trigger, + test_pattern, mask_byte, subcountL, subcountH + }; + + result = usbat_send_control(us, + usb_sndctrlpipe(us->pusb_dev,0), + 0x80, + 0x40, + 0, + 0, + command, + 8); + + // result = usbat_bulk_transport(us, command, 8, 0, NULL, 0, 0); + + return result; +} + +int usbat_read_block(struct us_data *us, + unsigned char access, + unsigned char reg, + unsigned char *content, + unsigned short len, + int use_sg) { + + int result; + unsigned char command[8] = { + 0xC0, access|0x02, reg, 0x00, 0x00, 0x00, + LSB_of(len), MSB_of(len) + }; + + result = usbat_send_control(us, + usb_sndctrlpipe(us->pusb_dev,0), + 0x80, + 0x40, + 0, + 0, + command, + 8); + + if (result != USB_STOR_TRANSPORT_GOOD) + return result; + + result = usbat_bulk_transport(us, + NULL, 0, SCSI_DATA_READ, content, len, use_sg); + + // result = usbat_bulk_transport(us, + // command, 8, 0, content, len, use_sg); + + return result; +} + +/* + * Block, waiting for an ATA device to become not busy or to report + * an error condition. + */ + +int usbat_wait_not_busy(struct us_data *us) { + + int i; + int result; + unsigned char status; + + /* Synchronizing cache on a CDR could take a heck of a long time, + but probably not more than 15 minutes or so */ + + for (i=0; i<500; i++) { + result = usbat_read(us, USBAT_ATA, 0x17, &status); + US_DEBUGP("SCM: Write ATA data status is %02X\n", status); + if (result!=USB_STOR_TRANSPORT_GOOD) + return result; + if (status&0x01) // check condition + return USB_STOR_TRANSPORT_FAILED; + if (status&0x20) // device fault + return USB_STOR_TRANSPORT_FAILED; + if ((status&0x80)!=0x80) // not busy + break; + if (i<5) + wait_ms(100); + else if (i<20) + wait_ms(500); + else if (i<49) + wait_ms(1000); + else if (i<499) + wait_ms(2000); + } + + if (i==500) + return USB_STOR_TRANSPORT_FAILED; + + return USB_STOR_TRANSPORT_GOOD; +} + +int usbat_write_block(struct us_data *us, + unsigned char access, + unsigned char reg, + unsigned char *content, + unsigned short len, + int use_sg) { + + int result; + unsigned char command[8] = { + 0x40, access|0x03, reg, 0x00, 0x00, 0x00, + LSB_of(len), MSB_of(len) + }; + + result = usbat_send_control(us, + usb_sndctrlpipe(us->pusb_dev,0), + 0x80, + 0x40, + 0, + 0, + command, + 8); + + if (result != USB_STOR_TRANSPORT_GOOD) + return result; + + result = usbat_bulk_transport(us, + NULL, 0, SCSI_DATA_WRITE, content, len, use_sg); + + if (result != USB_STOR_TRANSPORT_GOOD) + return result; + + // result = usbat_bulk_transport(us, + // command, 8, 0, content, len, use_sg); + + return usbat_wait_not_busy(us); +} + +int usbat_write_block_test(struct us_data *us, + unsigned char access, + unsigned char *registers, + unsigned char *data_out, + unsigned short num_registers, + unsigned char data_reg, + unsigned char status_reg, + unsigned char qualifier, + unsigned char timeout, + unsigned char *content, + unsigned short len, + int use_sg) { + + int result; + + // Not really sure the 0x07, 0x17, 0xfc, 0xe7 is necessary here, + // but that's what came out of the trace. + + unsigned char command[16] = { + 0x40, access|0x07, 0x07, 0x17, 0xfc, 0xe7, + LSB_of(num_registers*2), MSB_of(num_registers*2), + 0x40, access|0x05, data_reg, status_reg, + qualifier, timeout, LSB_of(len), MSB_of(len) + }; + int i; + unsigned char data[num_registers*2]; + int transferred; + struct scatterlist *sg; + char string[64]; + + for (i=0; ipusb_dev,0), + 0x80, + 0x40, + 0, + 0, + command, + 16); + + if (result != USB_STOR_TRANSPORT_GOOD) + return result; + + result = usbat_bulk_transport(us, + NULL, 0, SCSI_DATA_WRITE, data, num_registers*2, 0); + + // result = usbat_bulk_transport(us, + // command, 16, 0, data, num_registers*2, 0); + + if (result!=USB_STOR_TRANSPORT_GOOD) + return result; + + // transferred = 0; + + US_DEBUGP("Transfer out %d bytes, sg buffers %d\n", + len, use_sg); + + result = usbat_bulk_transport(us, + NULL, 0, SCSI_DATA_WRITE, content, len, use_sg); + +/* + if (!use_sg) { + + // Debug-print the first 48 bytes of the transfer + + string[0] = 0; + for (i=0; i sg[i].length ? + sg[i].length : len-transferred); + if (result!=US_BULK_TRANSFER_GOOD) + break; + transferred += sg[i].length; + } + } +*/ + if (result!=USB_STOR_TRANSPORT_GOOD) + return result; + + return usbat_wait_not_busy(us); +} + +int usbat_multiple_write(struct us_data *us, + unsigned char access, + unsigned char *registers, + unsigned char *data_out, + unsigned short num_registers) { + + int result; + unsigned char data[num_registers*2]; + int i; + unsigned char command[8] = { + 0x40, access|0x07, 0x00, 0x00, 0x00, 0x00, + LSB_of(num_registers*2), MSB_of(num_registers*2) + }; + + for (i=0; ipusb_dev,0), + 0x80, + 0x40, + 0, + 0, + command, + 8); + + if (result != USB_STOR_TRANSPORT_GOOD) + return result; + + result = usbat_bulk_transport(us, + NULL, 0, SCSI_DATA_WRITE, data, num_registers*2, 0); + + // result = usbat_bulk_transport(us, cmd, 8, 0, + // data, num_registers*2, 0); + + if (result!=USB_STOR_TRANSPORT_GOOD) + return result; + + return usbat_wait_not_busy(us); +} + +int usbat_read_user_io(struct us_data *us, + unsigned char *data_flags) { + + unsigned char command[8] = { + 0xC0, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + int result; + + result = usbat_send_control(us, + usb_rcvctrlpipe(us->pusb_dev,0), + 0x82, + 0xC0, + 0, + 0, + data_flags, + 1); + + // result = usbat_send_control(us, command, data_flags, 1); + + return result; +} + +int usbat_write_user_io(struct us_data *us, + unsigned char enable_flags, + unsigned char data_flags) { + + unsigned char command[8] = { + 0x40, 0x82, enable_flags, data_flags, 0x00, 0x00, 0x00, 0x00 + }; + int result; + + result = usbat_send_control(us, + usb_sndctrlpipe(us->pusb_dev,0), + 0x82, + 0x40, + short_pack(enable_flags, data_flags), + 0, + NULL, + 0); + + // result = usbat_send_control(us, command, NULL, 0); + + return result; +} + +static int hp_8200e_select_and_test_registers(struct us_data *us) { + + int result; + int selector; + unsigned char status; + + // try device = master, then device = slave. + + for (selector = 0xA0; selector <= 0xB0; selector += 0x10) { + + if ( (result = usbat_write(us, USBAT_ATA, 0x16, selector)) != + USB_STOR_TRANSPORT_GOOD) + return result; + + if ( (result = usbat_read(us, USBAT_ATA, 0x17, &status)) != + USB_STOR_TRANSPORT_GOOD) + return result; + + if ( (result = usbat_read(us, USBAT_ATA, 0x16, &status)) != + USB_STOR_TRANSPORT_GOOD) + return result; + + if ( (result = usbat_read(us, USBAT_ATA, 0x14, &status)) != + USB_STOR_TRANSPORT_GOOD) + return result; + + if ( (result = usbat_read(us, USBAT_ATA, 0x15, &status)) != + USB_STOR_TRANSPORT_GOOD) + return result; + + if ( (result = usbat_write(us, USBAT_ATA, 0x14, 0x55)) != + USB_STOR_TRANSPORT_GOOD) + return result; + + if ( (result = usbat_write(us, USBAT_ATA, 0x15, 0xAA)) != + USB_STOR_TRANSPORT_GOOD) + return result; + + if ( (result = usbat_read(us, USBAT_ATA, 0x14, &status)) != + USB_STOR_TRANSPORT_GOOD) + return result; + + if ( (result = usbat_read(us, USBAT_ATA, 0x15, &status)) != + USB_STOR_TRANSPORT_GOOD) + return result; + } + + return result; +} + +static int init_8200e(struct us_data *us) { + + int result; + unsigned char status; + + // Enable peripheral control signals + + if ( (result = usbat_write_user_io(us, + USBAT_UIO_OE1 | USBAT_UIO_OE0, + USBAT_UIO_EPAD | USBAT_UIO_1)) != USB_STOR_TRANSPORT_GOOD) + return result; + + US_DEBUGP("INIT 1\n"); + + wait_ms(2000); + + if ( (result = usbat_read_user_io(us, &status)) != + USB_STOR_TRANSPORT_GOOD) + return result; + + US_DEBUGP("INIT 2\n"); + + if ( (result = usbat_read_user_io(us, &status)) != + USB_STOR_TRANSPORT_GOOD) + return result; + + US_DEBUGP("INIT 3\n"); + + // Reset peripheral, enable periph control signals + // (bring reset signal up) + + if ( (result = usbat_write_user_io(us, + USBAT_UIO_DRVRST | USBAT_UIO_OE1 | USBAT_UIO_OE0, + USBAT_UIO_EPAD | USBAT_UIO_1)) != USB_STOR_TRANSPORT_GOOD) + return result; + + US_DEBUGP("INIT 4\n"); + + // Enable periph control signals + // (bring reset signal down) + + if ( (result = usbat_write_user_io(us, + USBAT_UIO_OE1 | USBAT_UIO_OE0, + USBAT_UIO_EPAD | USBAT_UIO_1)) != USB_STOR_TRANSPORT_GOOD) + return result; + + US_DEBUGP("INIT 5\n"); + + wait_ms(250); + + // Write 0x80 to ISA port 0x3F + + if ( (result = usbat_write(us, USBAT_ISA, 0x3F, 0x80)) != + USB_STOR_TRANSPORT_GOOD) + return result; + + US_DEBUGP("INIT 6\n"); + + // Read ISA port 0x27 + + if ( (result = usbat_read(us, USBAT_ISA, 0x27, &status)) != + USB_STOR_TRANSPORT_GOOD) + return result; + + US_DEBUGP("INIT 7\n"); + + if ( (result = usbat_read_user_io(us, &status)) != + USB_STOR_TRANSPORT_GOOD) + return result; + + US_DEBUGP("INIT 8\n"); + + if ( (result = hp_8200e_select_and_test_registers(us)) != + USB_STOR_TRANSPORT_GOOD) + return result; + + US_DEBUGP("INIT 9\n"); + + if ( (result = usbat_read_user_io(us, &status)) != + USB_STOR_TRANSPORT_GOOD) + return result; + + US_DEBUGP("INIT 10\n"); + + // Enable periph control signals and card detect + + if ( (result = usbat_write_user_io(us, + USBAT_UIO_ACKD |USBAT_UIO_OE1 | USBAT_UIO_OE0, + USBAT_UIO_EPAD | USBAT_UIO_1)) != USB_STOR_TRANSPORT_GOOD) + return result; + + US_DEBUGP("INIT 11\n"); + + if ( (result = usbat_read_user_io(us, &status)) != + USB_STOR_TRANSPORT_GOOD) + return result; + + US_DEBUGP("INIT 12\n"); + + wait_ms(1400); + + if ( (result = usbat_read_user_io(us, &status)) != + USB_STOR_TRANSPORT_GOOD) + return result; + + US_DEBUGP("INIT 13\n"); + + if ( (result = hp_8200e_select_and_test_registers(us)) != + USB_STOR_TRANSPORT_GOOD) + return result; + + US_DEBUGP("INIT 14\n"); + + if ( (result = usbat_set_shuttle_features(us, + 0x83, 0x00, 0x88, 0x08, 0x15, 0x14)) != + USB_STOR_TRANSPORT_GOOD) + return result; + + US_DEBUGP("INIT 15\n"); + + return result; +} + +/* + * Transport for the HP 8200e + */ +int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us) +{ + int result; + unsigned char status; + unsigned char registers[32]; + unsigned char data[32]; + unsigned int len; + int i; + char string[64]; + + /* This table tells us: + X = command not supported + L = return length in cmnd[4] (8 bits). + H = return length in cmnd[7] and cmnd[8] (16 bits). + D = return length in cmnd[6] to cmnd[9] (32 bits). + B = return length/blocksize in cmnd[6] to cmnd[8]. + T = return length in cmnd[6] to cmnd[8] (24 bits). + 0-9 = fixed return length + W = 24 bytes + h = return length/2048 in cmnd[7-8]. + */ + + static char *lengths = + + /* 0123456789ABCDEF 0123456789ABCDEF */ + + "0XXL0XXXXXXXXXXX" "XXLXXXXXXXX0XX0X" /* 00-1F */ + "XXXXX8XXhXH0XXX0" "XXXXX0XXXXXXXXXX" /* 20-3F */ + "XXHHL0X0XXH0XX0X" "XHH00HXX0TH0H0XX" /* 40-5F */ + "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 60-7F */ + "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 80-9F */ + "X0XXX0XXDXDXXXXX" "XXXXXXXXX000XHBX" /* A0-BF */ + "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* C0-DF */ + "XDXXXXXXXXXXXXXX" "XXW00HXXXXXXXXXX"; /* E0-FF */ + + if (us->flags & US_FL_NEED_INIT) { + US_DEBUGP("8200e: initializing\n"); + init_8200e(us); + us->flags &= ~US_FL_NEED_INIT; + } + + len = srb->request_bufflen; + +/* if (srb->sc_data_direction == SCSI_DATA_WRITE) + len = srb->request_bufflen; + else { + + switch (lengths[srb->cmnd[0]]) { + + case 'L': + len = srb->cmnd[4]; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + len = lengths[srb->cmnd[0]]-'0'; + break; + case 'H': + len = (((unsigned int)srb->cmnd[7])<<8) | srb->cmnd[8]; + break; + case 'h': + len = (((unsigned int)srb->cmnd[7])<<8) | srb->cmnd[8]; + len <<= 11; // *2048 + break; + case 'T': + len = (((unsigned int)srb->cmnd[6])<<16) | + (((unsigned int)srb->cmnd[7])<<8) | + srb->cmnd[8]; + break; + case 'D': + len = (((unsigned int)srb->cmnd[6])<<24) | + (((unsigned int)srb->cmnd[7])<<16) | + (((unsigned int)srb->cmnd[8])<<8) | + srb->cmnd[9]; + break; + case 'W': + len = 24; + break; + case 'B': + // Let's try using the command structure's + // request_bufflen here + len = srb->request_bufflen; + break; + default: + US_DEBUGP("Error: UNSUPPORTED COMMAND %02X\n", + srb->cmnd[0]); + return USB_STOR_TRANSPORT_ERROR; + } + } */ + + if (len > 0xFFFF) { + US_DEBUGP("Error: len = %08X... what do I do now?\n", + len); + return USB_STOR_TRANSPORT_ERROR; + } + + // US_DEBUGP("XXXXXXXXXXXXXXXX req_bufflen %d, len %d, bufflen %d\n", + // srb->request_bufflen, len, srb->bufflen); + + /* Send A0 (ATA PACKET COMMAND). + Note: I guess we're never going to get any of the ATA + commands... just ATA Packet Commands. + */ + + registers[0] = 0x11; + registers[1] = 0x12; + registers[2] = 0x13; + registers[3] = 0x14; + registers[4] = 0x15; + registers[5] = 0x16; + registers[6] = 0x17; + data[0] = 0x00; + data[1] = 0x00; + data[2] = 0x00; + data[3] = len&0xFF; // (cylL) = expected length (L) + data[4] = (len>>8)&0xFF; // (cylH) = expected length (H) + data[5] = 0xB0; // (device sel) = slave + data[6] = 0xA0; // (command) = ATA PACKET COMMAND + + if (srb->sc_data_direction == SCSI_DATA_WRITE) { + + for (i=7; i<19; i++) { + registers[i] = 0x10; + data[i] = (i-7 >= srb->cmd_len) ? 0 : srb->cmnd[i-7]; + } + + result = usbat_write_block_test(us, USBAT_ATA, + registers, data, 19, + 0x10, 0x17, 0xFD, 0x30, + srb->request_buffer, + len, srb->use_sg); + + return result; + } + + if ( (result = usbat_multiple_write(us, + USBAT_ATA, + registers, data, 7)) != USB_STOR_TRANSPORT_GOOD) { + return result; + } + + // Write the 12-byte command header. + + if ( (result = usbat_write_block(us, + USBAT_ATA, 0x10, srb->cmnd, 12, 0)) != + USB_STOR_TRANSPORT_GOOD) { + return result; + } + + // If there is response data to be read in + // then do it here. + + if (len != 0 && (srb->sc_data_direction == SCSI_DATA_READ)) { + + // How many bytes to read in? Check cylL register + + if ( (result = usbat_read(us, USBAT_ATA, 0x14, &status)) != + USB_STOR_TRANSPORT_GOOD) { + return result; + } + + if (len>0xFF) { // need to read cylH also + len = status; + if ( (result = usbat_read(us, USBAT_ATA, 0x15, + &status)) != + USB_STOR_TRANSPORT_GOOD) { + return result; + } + len += ((unsigned int)status)<<8; + } + else + len = status; + + + result = usbat_read_block(us, USBAT_ATA, 0x10, + srb->request_buffer, len, srb->use_sg); + + /* Debug-print the first 32 bytes of the transfer */ + + if (!srb->use_sg) { + string[0] = 0; + for (i=0; irequest_buffer)[i]); + if ((i%16)==15) { + US_DEBUGP("%s\n", string); + string[0] = 0; + } + } + if (string[0]!=0) + US_DEBUGP("%s\n", string); + } + } + + // US_DEBUGP("Command result %d\n", result); + + return result; +} + + diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/storage/shuttle_usbat.h linux/drivers/usb/storage/shuttle_usbat.h --- v2.4.0-test5/linux/drivers/usb/storage/shuttle_usbat.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/storage/shuttle_usbat.h Mon Jul 31 10:34:27 2000 @@ -0,0 +1,76 @@ +/* Driver for SCM Microsystems USB-ATAPI cable + * Header File + * + * Current development and maintainance by: + * (c) 2000 Robert Baruch (autophile@dol.net) + * + * See scm.c for more explanation + * + * 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, 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. + */ + +#ifndef _USB_SHUTTLE_USBAT_H +#define _USB_SHUTTLE_USBAT_H + +#define USBAT_EPP_PORT 0x10 +#define USBAT_EPP_REGISTER 0x30 +#define USBAT_ATA 0x40 +#define USBAT_ISA 0x50 + +/* SCM User I/O Data registers */ + +#define USBAT_UIO_EPAD 0x80 // Enable Peripheral Control Signals +#define USBAT_UIO_CDT 0x40 // Card Detect (Read Only) + // CDT = ACKD & !UI1 & !UI0 +#define USBAT_UIO_1 0x20 // I/O 1 +#define USBAT_UIO_0 0x10 // I/O 0 +#define USBAT_UIO_EPP_ATA 0x08 // 1=EPP mode, 0=ATA mode +#define USBAT_UIO_UI1 0x04 // Input 1 +#define USBAT_UIO_UI0 0x02 // Input 0 +#define USBAT_UIO_INTR_ACK 0x01 // Interrupt (ATA & ISA)/Acknowledge (EPP) + +/* SCM User I/O Enable registers */ + +#define USBAT_UIO_DRVRST 0x80 // Reset Peripheral +#define USBAT_UIO_ACKD 0x40 // Enable Card Detect +#define USBAT_UIO_OE1 0x20 // I/O 1 set=output/clr=input + // If ACKD=1, set OE1 to 1 also. +#define USBAT_UIO_OE0 0x10 // I/O 0 set=output/clr=input +#define USBAT_UIO_ADPRST 0x01 // Reset SCM chip + +/* USBAT-specific commands */ + +extern int usbat_read(struct us_data *us, unsigned char access, + unsigned char reg, unsigned char *content); +extern int usbat_write(struct us_data *us, unsigned char access, + unsigned char reg, unsigned char content); +extern int usbat_read_block(struct us_data *us, unsigned char access, + unsigned char reg, unsigned char *content, unsigned short len, + int use_sg); +extern int usbat_write_block(struct us_data *us, unsigned char access, + unsigned char reg, unsigned char *content, unsigned short len, + int use_sg); +extern int usbat_multiple_write(struct us_data *us, unsigned char access, + unsigned char *registers, unsigned char *data_out, + unsigned short num_registers); +extern int usbat_read_user_io(struct us_data *us, unsigned char *data_flags); +extern int usbat_write_user_io(struct us_data *us, + unsigned char enable_flags, unsigned char data_flags); + +/* HP 8200e stuff */ + +extern int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us); + +#endif diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/storage/transport.c linux/drivers/usb/storage/transport.c --- v2.4.0-test5/linux/drivers/usb/storage/transport.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/storage/transport.c Tue Aug 1 18:54:58 2000 @@ -1,6 +1,6 @@ /* Driver for USB Mass Storage compliant devices * - * $Id: transport.c,v 1.3 2000/07/20 01:06:40 mdharm Exp $ + * $Id: transport.c,v 1.5 2000/07/28 22:40:20 mdharm Exp $ * * Current development and maintainance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -203,7 +203,7 @@ int pipe; /* calculate the appropriate pipe information */ - if (US_DIRECTION(us->srb->cmnd[0])) + if (us->srb->sc_data_direction == SCSI_DATA_READ) pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); else pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out); @@ -258,7 +258,7 @@ * function simply determines if we're going to use scatter-gather or not, * and acts appropriately. For now, it also re-interprets the error codes. */ -static void us_transfer(Scsi_Cmnd *srb, struct us_data* us, int dir_in) +static void us_transfer(Scsi_Cmnd *srb, struct us_data* us) { int i; int result = -1; @@ -414,8 +414,9 @@ if (need_auto_sense) { int temp_result; void* old_request_buffer; - int old_sg; - int old_request_bufflen; + unsigned short old_sg; + unsigned old_request_bufflen; + unsigned char old_sc_data_direction; unsigned char old_cmnd[MAX_COMMAND_SIZE]; US_DEBUGP("Issuing auto-REQUEST_SENSE\n"); @@ -431,13 +432,21 @@ srb->cmnd[4] = 18; srb->cmnd[5] = 0; - /* set the buffer length for transfer */ + /* set the transfer direction */ + old_sc_data_direction = srb->sc_data_direction; + srb->sc_data_direction = SCSI_DATA_READ; + + /* use the new buffer we have */ old_request_buffer = srb->request_buffer; + srb->request_buffer = srb->sense_buffer; + + /* set the buffer length for transfer */ old_request_bufflen = srb->request_bufflen; + srb->request_bufflen = 18; + + /* set up for no scatter-gather use */ old_sg = srb->use_sg; srb->use_sg = 0; - srb->request_bufflen = 18; - srb->request_buffer = srb->sense_buffer; /* issue the auto-sense command */ temp_result = us->transport(us->srb, us); @@ -462,6 +471,7 @@ srb->request_buffer = old_request_buffer; srb->request_bufflen = old_request_bufflen; srb->use_sg = old_sg; + srb->sc_data_direction = old_sc_data_direction; memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE); /* If things are really okay, then let's show that */ @@ -555,7 +565,7 @@ /* DATA STAGE */ /* transfer the data payload for this command, if one exists*/ if (us_transfer_length(srb, us)) { - us_transfer(srb, us, US_DIRECTION(srb->cmnd[0])); + us_transfer(srb, us); US_DEBUGP("CBI data stage result is 0x%x\n", srb->result); /* if it was aborted, we need to indicate that */ @@ -656,7 +666,7 @@ /* DATA STAGE */ /* transfer the data payload for this command, if one exists*/ if (us_transfer_length(srb, us)) { - us_transfer(srb, us, US_DIRECTION(srb->cmnd[0])); + us_transfer(srb, us); US_DEBUGP("CB data stage result is 0x%x\n", srb->result); /* if it was aborted, we need to indicate that */ @@ -707,6 +717,8 @@ return 0; } +int usb_stor_Bulk_reset(struct us_data *us); + int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) { struct bulk_cb_wrap bcb; @@ -718,7 +730,7 @@ /* set up the command wrapper */ bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb.DataTransferLength = cpu_to_le32(us_transfer_length(srb, us)); - bcb.Flags = US_DIRECTION(srb->cmnd[0]) << 7; + bcb.Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0; bcb.Tag = srb->serial_number; bcb.Lun = srb->cmnd[1] >> 5; bcb.Length = srb->cmd_len; @@ -755,7 +767,7 @@ if (result == 0) { /* send/receive data payload, if there is any */ if (bcb.DataTransferLength) { - us_transfer(srb, us, bcb.Flags); + us_transfer(srb, us); US_DEBUGP("Bulk data transfer result 0x%x\n", srb->result); @@ -810,7 +822,7 @@ } /* check bulk status */ - US_DEBUGP("Bulk status S 0x%x T 0x%x R %d V 0x%x\n", + US_DEBUGP("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n", le32_to_cpu(bcs.Signature), bcs.Tag, bcs.Residue, bcs.Status); if (bcs.Signature != cpu_to_le32(US_BULK_CS_SIGN) || @@ -832,6 +844,7 @@ case US_BULK_STAT_PHASE: /* phase error */ + usb_stor_Bulk_reset(us); return USB_STOR_TRANSPORT_ERROR; } @@ -873,10 +886,14 @@ return 0; } -/* FIXME: Does this work? */ +/* This issues a Bulk-only Reset to the device in question, including + * clearing the subsequent endpoint halts that may occur. + */ int usb_stor_Bulk_reset(struct us_data *us) { int result; + + US_DEBUGP("Bulk reset requested\n"); result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0), diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/storage/transport.h linux/drivers/usb/storage/transport.h --- v2.4.0-test5/linux/drivers/usb/storage/transport.h Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/storage/transport.h Mon Jul 31 10:34:27 2000 @@ -1,7 +1,7 @@ /* Driver for USB Mass Storage compliant devices * Transport Functions Header File * - * $Id: transport.h,v 1.4 2000/07/23 18:40:38 groovyjava Exp $ + * $Id: transport.h,v 1.6 2000/07/27 14:42:43 groovyjava Exp $ * * Current development and maintainance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -46,10 +46,6 @@ #include "usb.h" #include "scsi.h" -/* bit set if input */ -extern unsigned char us_direction[256/8]; -#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1) - /* Protocols */ #define US_PR_CBI 0x00 /* Control/Bulk/Interrupt */ @@ -59,7 +55,8 @@ #define US_PR_SCM_ATAPI 0x80 /* SCM-ATAPI bridge */ #endif #ifdef CONFIG_USB_STORAGE_SDDR09 -#define US_PR_SCM_SCSI 0x81 /* SCM-SCSI bridge */ +#define US_PR_EUSB_SDDR09 0x81 /* SCM-SCSI bridge for + SDDR-09 */ #endif /* diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/storage/usb.c linux/drivers/usb/storage/usb.c --- v2.4.0-test5/linux/drivers/usb/storage/usb.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/storage/usb.c Tue Aug 1 18:54:58 2000 @@ -1,6 +1,6 @@ /* Driver for USB Mass Storage compliant devices * - * $Id: usb.c,v 1.11 2000/07/24 20:37:24 mdharm Exp $ + * $Id: usb.c,v 1.16 2000/08/01 22:01:19 mdharm Exp $ * * Current development and maintainance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -50,8 +50,11 @@ #include "transport.h" #include "protocol.h" #include "debug.h" -#if defined(CONFIG_USB_STORAGE_HP8200e) || defined(CONFIG_USB_STORAGE_SDDR09) -#include "scm.h" +#ifdef CONFIG_USB_STORAGE_HP8200e +#include "shuttle_usbat.h" +#endif +#ifdef CONFIG_USB_STORAGE_SDDR09 +#include "sddr09.h" #endif #include @@ -117,9 +120,9 @@ /* signal that we've started the thread */ up(&(us->notify)); + set_current_state(TASK_INTERRUPTIBLE); for(;;) { - set_current_state(TASK_INTERRUPTIBLE); US_DEBUGP("*** thread sleeping.\n"); schedule(); US_DEBUGP("*** thread awakened.\n"); @@ -137,15 +140,27 @@ switch (action) { case US_ACT_COMMAND: + /* reject the command if the direction indicator + * is UNKNOWN + */ + if (us->srb->sc_data_direction == SCSI_DATA_UNKNOWN) { + US_DEBUGP("UNKNOWN data direction\n"); + us->srb->result = DID_ERROR; + set_current_state(TASK_INTERRUPTIBLE); + us->srb->scsi_done(us->srb); + us->srb = NULL; + break; + } + /* reject if target != 0 or if LUN is higher than * the maximum known LUN */ if (us->srb->target || (us->srb->lun > us->max_lun)) { US_DEBUGP("Bad device number (%d/%d)\n", us->srb->target, us->srb->lun); - us->srb->result = DID_BAD_TARGET << 16; + set_current_state(TASK_INTERRUPTIBLE); us->srb->scsi_done(us->srb); us->srb = NULL; break; @@ -155,6 +170,8 @@ if ((us->srb->cmnd[0] == START_STOP) && (us->flags & US_FL_START_STOP)) { us->srb->result = GOOD; + + set_current_state(TASK_INTERRUPTIBLE); us->srb->scsi_done(us->srb); us->srb = NULL; break; @@ -194,9 +211,11 @@ if (us->srb->result != DID_ABORT << 16) { US_DEBUGP("scsi cmd done, result=0x%x\n", us->srb->result); + set_current_state(TASK_INTERRUPTIBLE); us->srb->scsi_done(us->srb); } else { US_DEBUGP("scsi command aborted\n"); + set_current_state(TASK_INTERRUPTIBLE); up(&(us->notify)); } us->srb = NULL; @@ -253,12 +272,12 @@ US_SC_UFI, US_PR_CBI, US_FL_SINGLE_LUN}, { 0x0693, 0x0002, 0x0100, 0x0100, "Hagiwara FlashGate SmartMedia", US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, - { 0x0781, 0x0001, 0x0200, 0x0200, "Sandisk ImageMate (SDDR-01)", + { 0x0781, 0x0001, 0x0200, 0x0200, "Sandisk ImageMate (SDDR-05a)", US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN | US_FL_START_STOP}, #ifdef CONFIG_USB_STORAGE_SDDR09 { 0x0781, 0x0200, 0x0100, 0x0100, "Sandisk ImageMate (SDDR-09)", - US_SC_SCSI, US_PR_SCM_SCSI, - US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_NEED_INIT}, + US_SC_SCSI, US_PR_EUSB_SDDR09, + US_FL_SINGLE_LUN | US_FL_START_STOP}, #endif { 0x0781, 0x0002, 0x0009, 0x0009, "Sandisk Imagemate (SDDR-31)", US_SC_SCSI, US_PR_BULK, US_FL_IGNORE_SER}, @@ -447,7 +466,7 @@ /* set the interface -- STALL is an acceptable response here */ #ifdef CONFIG_USB_STORAGE_SDDR09 - if (protocol != US_PR_SCM_SCSI) + if (protocol != US_PR_EUSB_SDDR09) result = usb_set_interface(dev, altsetting->bInterfaceNumber, 0); else @@ -631,8 +650,8 @@ #endif #ifdef CONFIG_USB_STORAGE_SDDR09 - case US_PR_SCM_SCSI: - ss->transport_name = "SCM/SCSI"; + case US_PR_EUSB_SDDR09: + ss->transport_name = "EUSB/SDDR09"; ss->transport = sddr09_transport; ss->transport_reset = usb_stor_CB_reset; ss->max_lun = 1; @@ -666,13 +685,7 @@ case US_SC_QIC: ss->protocol_name = "QIC-157"; - US_DEBUGP("Sorry, device not supported. Please\n"); - US_DEBUGP("contact mdharm-usb@one-eyed-alien.net\n"); - US_DEBUGP("if you see this message.\n"); - up(&us_list_semaphore); - kfree(ss->current_urb); - kfree(ss); - return NULL; + ss->proto_handler = usb_stor_qic157_command; break; case US_SC_8070: @@ -843,6 +856,16 @@ /* Now that scsi_unregister_module is done with the host * template, we can free the us_data structure (the host * template is inline in this structure). */ + + /* If there's extra data in the us_data structure then + * free that first */ + + if (us_list->extra) { + if (us_list->extra_destructor) + (*us_list->extra_destructor)( + us_list->extra); + kfree(us_list->extra); + } kfree (us_list); /* advance the list pointer */ @@ -855,3 +878,6 @@ module_init(usb_stor_init) ; module_exit(usb_stor_exit) ; + +MODULE_AUTHOR("Michael Gee , David L. Brown, Jr. , Matthew Dharm "); +MODULE_DESCRIPTION("USB Mass Storage driver"); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/storage/usb.h linux/drivers/usb/storage/usb.h --- v2.4.0-test5/linux/drivers/usb/storage/usb.h Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/storage/usb.h Tue Aug 1 18:54:58 2000 @@ -1,7 +1,7 @@ /* Driver for USB Mass Storage compliant devices * Main Header File * - * $Id: usb.h,v 1.3 2000/07/20 01:14:56 mdharm Exp $ + * $Id: usb.h,v 1.4 2000/07/28 20:14:49 groovyjava Exp $ * * Current development and maintainance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -176,6 +176,8 @@ /* mutual exclusion structures */ struct semaphore notify; /* thread begin/end */ struct semaphore queue_exclusion; /* to protect data structs */ + void *extra; /* Any extra data */ + void (*extra_destructor)(void *); /* extra data destructor */ }; /* The list of structures and the protective lock for them */ diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c --- v2.4.0-test5/linux/drivers/usb/uhci.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/uhci.c Thu Jul 27 18:36:54 2000 @@ -49,6 +49,7 @@ static int debug = 1; MODULE_PARM(debug, "i"); +MODULE_PARM_DESC(debug, "Debug level"); static kmem_cache_t *uhci_td_cachep; static kmem_cache_t *uhci_qh_cachep; @@ -2541,5 +2542,8 @@ pm_unregister_all(handle_pm_event); uhci_cleanup(); } + +MODULE_AUTHOR("Linus Torvalds, Johannes Erdfelt, Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber"); +MODULE_DESCRIPTION("USB Universal Host Controller Interface driver"); #endif //MODULE diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/usb-ohci.c linux/drivers/usb/usb-ohci.c --- v2.4.0-test5/linux/drivers/usb/usb-ohci.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/usb-ohci.c Sun Aug 6 11:23:36 2000 @@ -65,6 +65,9 @@ */ #include #include +#ifndef CONFIG_PM +#define CONFIG_PM +#endif #endif @@ -415,9 +418,11 @@ int i, size = 0; unsigned long flags; - if (!urb->dev || !urb->dev->bus) return -EINVAL; + if (!urb->dev || !urb->dev->bus) + return -EINVAL; - if (urb->hcpriv) return -EINVAL; /* urb already in use */ + if (urb->hcpriv) /* urb already in use */ + return -EINVAL; // if(usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe))) // return -EPIPE; @@ -435,8 +440,10 @@ /* when controller's hung, permit only roothub cleanup attempts * such as powering down ports */ - if (ohci->disabled) + if (ohci->disabled) { + usb_dec_dev_use (urb->dev); return -ESHUTDOWN; + } /* every endpoint has a ed, locate and fill it */ if (!(ed = ep_add_ed (urb->dev, pipe, urb->interval, 1))) { @@ -953,13 +960,20 @@ ed = ed_ret = &(usb_to_ohci (usb_dev)->ed[(usb_pipeendpoint (pipe) << 1) | (usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))]); - if((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) - return NULL; /* pending delete request */ + if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) { + /* pending delete request */ + spin_unlock (&usb_ed_lock); + return NULL; + } if (ed->state == ED_NEW) { ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); /* skip ed */ OHCI_ALLOC (td, sizeof (*td)); /* dummy td; end of td list for ed */ - if(!td) return NULL; /* out of memory */ + if (!td) { + /* out of memory */ + spin_unlock (&usb_ed_lock); + return NULL; + } ed->hwTailP = cpu_to_le32 (virt_to_bus (td)); ed->hwHeadP = ed->hwTailP; ed->state = ED_UNLINK; @@ -1730,7 +1744,9 @@ urb_print (urb, "RET(rh)", usb_pipeout (urb->pipe)); #endif - if (urb->complete) urb->complete (urb); + if (urb->complete) + urb->complete (urb); + usb_dec_dev_use (urb->dev); return 0; } @@ -1880,7 +1896,9 @@ ohci->ohci_dev->slot_name); // e.g. due to PCI Master/Target Abort -#ifndef DEBUG +#ifdef DEBUG + ohci_dump (ohci, 1); +#else // FIXME: be optimistic, hope that bug won't repeat often. // Make some non-interrupt context restart the controller. // Count and limit the retries though; either hardware or @@ -1910,6 +1928,8 @@ } writel (ints, ®s->intrstatus); writel (OHCI_INTR_MIE, ®s->intrenable); + + /* FIXME: check URB timeouts */ } /*-------------------------------------------------------------------------*/ @@ -1921,7 +1941,7 @@ ohci_t * ohci; struct usb_bus * bus; - ohci = (ohci_t *) __get_free_pages (GFP_KERNEL, 1); + ohci = (ohci_t *) kmalloc (sizeof *ohci, GFP_KERNEL); if (!ohci) return NULL; @@ -1932,7 +1952,7 @@ bus = usb_alloc_bus (&sohci_device_operations); if (!bus) { - free_pages ((unsigned long) ohci, 1); + kfree (ohci); return NULL; } @@ -1974,7 +1994,7 @@ /* unmap the IO address space */ iounmap (ohci->regs); - free_pages ((unsigned long) ohci, 1); + kfree (ohci); } /*-------------------------------------------------------------------------*/ @@ -2085,13 +2105,27 @@ static int __devinit ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) { - unsigned long mem_resource; + unsigned long mem_resource, mem_len; u8 latency, limit; void *mem_base; if (pci_enable_device(dev) < 0) return -ENODEV; + /* we read its hardware registers as memory */ + mem_resource = pci_resource_start(dev, 0); + mem_len = pci_resource_len(dev, 0); + if (!request_mem_region (mem_resource, mem_len, ohci_pci_driver.name)) { + dbg ("controller already in use"); + return -EBUSY; + } + + mem_base = ioremap_nocache (mem_resource, mem_len); + if (!mem_base) { + err("Error mapping OHCI memory"); + return -EFAULT; + } + /* controller writes into our memory */ pci_set_master (dev); pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency); @@ -2103,15 +2137,6 @@ } } - /* we read its hardware registers as memory */ - mem_resource = pci_resource_start(dev, 0); - /* request_mem_region ... */ - mem_base = ioremap_nocache (mem_resource, 4096); - if (!mem_base) { - err("Error mapping OHCI memory"); - return -EFAULT; - } - return hc_found_ohci (dev, dev->irq, mem_base); } @@ -2145,6 +2170,8 @@ &ohci->regs->control); hc_release_ohci (ohci); + + release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0)); } @@ -2233,7 +2260,7 @@ /*-------------------------------------------------------------------------*/ -static const struct __devinitdata pci_device_id ohci_pci_ids [] = { { +static const struct pci_device_id __devinitdata ohci_pci_ids [] = { { /* handle any USB OHCI controller */ class: ((PCI_CLASS_SERIAL_USB << 8) | 0x10), @@ -2328,4 +2355,5 @@ #endif /* MODULE */ +MODULE_AUTHOR ("Roman Weissgaerber "); MODULE_DESCRIPTION ("USB OHCI Host Controller Driver"); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/usb-uhci.c linux/drivers/usb/usb-uhci.c --- v2.4.0-test5/linux/drivers/usb/usb-uhci.c Mon Jul 10 16:47:25 2000 +++ linux/drivers/usb/usb-uhci.c Thu Aug 3 17:20:49 2000 @@ -1,10 +1,10 @@ /* * Universal Host Controller Interface driver for USB (take II). * - * (c) 1999 Georg Acher, acher@in.tum.de (executive slave) (base guitar) - * Deti Fliegl, deti@fliegl.de (executive slave) (lead voice) - * Thomas Sailer, sailer@ife.ee.ethz.ch (chief consultant) (cheer leader) - * Roman Weissgaerber, weissg@vienna.at (virt root hub) (studio porter) + * (c) 1999-2000 Georg Acher, acher@in.tum.de (executive slave) (base guitar) + * Deti Fliegl, deti@fliegl.de (executive slave) (lead voice) + * Thomas Sailer, sailer@ife.ee.ethz.ch (chief consultant) (cheer leader) + * Roman Weissgaerber, weissg@vienna.at (virt root hub) (studio porter) * * HW-initalization based on material of * @@ -12,7 +12,7 @@ * (C) Copyright 1999 Johannes Erdfelt * (C) Copyright 1999 Randy Dunlap * - * $Id: usb-uhci.c,v 1.232 2000/06/11 13:18:30 acher Exp $ + * $Id: usb-uhci.c,v 1.236 2000/08/02 20:28:28 acher Exp $ */ #include @@ -48,7 +48,7 @@ /* This enables an extra UHCI slab for memory debugging */ #define DEBUG_SLAB -#define VERSTR "$Revision: 1.232 $ time " __TIME__ " " __DATE__ +#define VERSTR "$Revision: 1.236 $ time " __TIME__ " " __DATE__ #include #include "usb-uhci.h" @@ -791,7 +791,7 @@ char *data; unsigned int pipe = urb->pipe; int maxsze = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe)); - int info, len; + int info, len, last; int depth_first=USE_BULK_DEPTH_FIRST; // UHCI descriptor chasing method urb_priv_t *upriv, *bpriv; @@ -888,13 +888,15 @@ data += pktsze; len -= pktsze; - if (!len) + last = (len == 0 && (usb_pipein(pipe) || pktsze < maxsze || (urb->transfer_flags & USB_DISABLE_SPD))); + + if (last) td->hw.td.status |= TD_CTRL_IOC; // last one generates INT insert_td (s, qh, td, UHCI_PTR_DEPTH * depth_first); usb_dotoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)); - } while (len > 0); + } while (!last); list_add (&qh->desc_list, &urb_priv->desc_list); @@ -1036,11 +1038,18 @@ spin_lock_irqsave (&s->urb_list_lock, flags); + if (!in_interrupt()) // shouldn't be called from interrupt at all... + spin_lock(&urb->lock); + if (urb->status == -EINPROGRESS) { // URB probably still in work dequeue_urb (s, urb); uhci_switch_timer_int(s); s->unlink_urb_done=1; + + if (!in_interrupt()) + spin_unlock(&urb->lock); + spin_unlock_irqrestore (&s->urb_list_lock, flags); urb->status = -ENOENT; // mark urb as killed @@ -1076,10 +1085,13 @@ urb->complete ((struct urb *) urb); } usb_dec_dev_use (urb->dev); - return 0; } - else + else { + if (!in_interrupt()) + spin_unlock(&urb->lock); spin_unlock_irqrestore (&s->urb_list_lock, flags); + } + return 0; } /*-------------------------------------------------------------------*/ @@ -1198,9 +1210,10 @@ break; } ((urb_priv_t*)urb->hcpriv)->started = UHCI_GET_CURRENT_FRAME(s); + return -EINPROGRESS; // completion will follow } - return -EINPROGRESS; + return 0; // URB already dead } /*-------------------------------------------------------------------*/ _static int uhci_unlink_urb (urb_t *urb) @@ -1222,9 +1235,20 @@ if (urb->transfer_flags & USB_ASYNC_UNLINK) { int ret; - spin_lock_irqsave (&s->urb_list_lock, flags); + spin_lock_irqsave (&s->urb_list_lock, flags); + + // The URB needs to be locked if called outside completion context + + if (!in_interrupt()) + spin_lock(&urb->lock); + ret = uhci_unlink_urb_async(s, urb); - spin_unlock_irqrestore (&s->urb_list_lock, flags); + + if (!in_interrupt()) + spin_unlock(&urb->lock); + + spin_unlock_irqrestore (&s->urb_list_lock, flags); + return ret; } else @@ -1427,10 +1451,10 @@ #ifdef ISO_SANITY_CHECK if(urb->iso_frame_desc[n].length > maxsze) { + err("submit_iso: urb->iso_frame_desc[%d].length(%d)>%d",n , urb->iso_frame_desc[n].length, maxsze); tdm[n] = 0; - ret=-EINVAL; - goto inval; + ret=-EINVAL; } else #endif @@ -2177,10 +2201,9 @@ usb_endpoint_halt (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); } - if (status != 0) { // if any error occured stop processing of further TDs + if (status && (status != -EPIPE)) { // if any error occurred stop processing of further TDs // only set ret if status returned an error - if (status != -EPIPE) - uhci_show_td (desc); + is_error: ret = status; urb->error_count++; break; @@ -2212,6 +2235,8 @@ data_toggle = uhci_toggle (desc->hw.td.info); break; } + else if (status) + goto is_error; data_toggle = uhci_toggle (desc->hw.td.info); queue_dbg("process_transfer: len:%d status:%x mapped:%x toggle:%d", actual_length, desc->hw.td.status,status, data_toggle); @@ -2457,10 +2482,11 @@ is_ring = 1; } + spin_lock(&urb->lock); spin_unlock(&s->urb_list_lock); - // In case you need the current URB status for your completion handler - if (urb->complete && (!proceed || (urb->transfer_flags & USB_URB_EARLY_COMPLETE))) { + // In case you need the current URB status for your completion handler (before resubmit) + if (urb->complete && (!proceed )) { dbg("process_transfer: calling early completion"); urb->complete ((struct urb *) urb); if (!proceed && is_ring && (urb->status != -ENOENT)) @@ -2478,15 +2504,15 @@ } while (tmp != NULL && tmp != urb->next); // submit until we reach NULL or our own pointer or submit fails - if (urb->complete && !(urb->transfer_flags & USB_URB_EARLY_COMPLETE)) { + if (urb->complete) { dbg("process_transfer: calling completion"); urb->complete ((struct urb *) urb); } } - spin_lock(&s->urb_list_lock); - usb_dec_dev_use (urb->dev); + spin_unlock(&urb->lock); + spin_lock(&s->urb_list_lock); } } @@ -2790,10 +2816,6 @@ break; /* disable legacy emulation */ pci_write_config_word (dev, USBLEGSUP, USBLEGSUP_DEFAULT); - if(dev->vendor==0x8086) { - info("Intel USB controller: setting latency timer to %d", UHCI_LATENCY_TIMER); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, UHCI_LATENCY_TIMER); - } return alloc_uhci(dev, dev->irq, io_addr, io_size); } @@ -2885,4 +2907,6 @@ uhci_cleanup (); } +MODULE_AUTHOR("Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber"); +MODULE_DESCRIPTION("USB Universal Host Controller Interface driver"); #endif //MODULE diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/usb.c linux/drivers/usb/usb.c --- v2.4.0-test5/linux/drivers/usb/usb.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/usb/usb.c Thu Aug 3 17:20:49 2000 @@ -775,8 +775,8 @@ void usb_free_dev(struct usb_device *dev) { if (atomic_dec_and_test(&dev->refcnt)) { - usb_destroy_configuration(dev); dev->bus->op->deallocate(dev); + usb_destroy_configuration(dev); kfree(dev); } } @@ -819,7 +819,7 @@ if (urb && urb->dev) return urb->dev->bus->op->submit_urb(urb); else - return -1; + return -ENODEV; } /*-------------------------------------------------------------------*/ @@ -828,7 +828,7 @@ if (urb && urb->dev) return urb->dev->bus->op->unlink_urb(urb); else - return -1; + return -ENODEV; } /*-------------------------------------------------------------------* * COMPLETION HANDLERS * @@ -1330,13 +1330,6 @@ } kfree(dev->config); } - -void usb_init_root_hub(struct usb_device *dev) -{ - dev->devnum = -1; - dev->slow = 0; - dev->actconfig = NULL; -} /* for returning string descriptors in UTF-16LE */ static int ascii2utf (char *ascii, __u8 *utf, int utfmax) @@ -1451,13 +1444,13 @@ usb_disconnect(child); } - /* remove /proc/bus/usb entry */ - usbdevfs_remove_device(dev); - - /* Free up the device itself, including its device number */ - if (dev->devnum > 0) + /* Free the device number and remove the /proc/bus/usb entry */ + if (dev->devnum > 0) { clear_bit(dev->devnum, &dev->bus->devmap.devicemap); + usbdevfs_remove_device(dev); + } + /* Free up the device itself */ usb_free_dev(dev); } @@ -1631,7 +1624,7 @@ if (result < 0) return result; - if (status & 1) + if (le16_to_cpu(status) & 1) return -EPIPE; /* still halted */ usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); @@ -1679,7 +1672,7 @@ } if (!cp) { warn("selecting invalid configuration %d", configuration); - return -1; + return -EINVAL; } if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), @@ -1719,12 +1712,12 @@ if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) { warn("too many configurations"); - return -1; + return -EINVAL; } if (dev->descriptor.bNumConfigurations < 1) { warn("not enough configurations"); - return -1; + return -EINVAL; } dev->config = (struct usb_config_descriptor *) @@ -1732,7 +1725,7 @@ sizeof(struct usb_config_descriptor), GFP_KERNEL); if (!dev->config) { err("out of memory"); - return -1; + return -ENOMEM; } memset(dev->config, 0, dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor)); @@ -1741,7 +1734,7 @@ dev->descriptor.bNumConfigurations, GFP_KERNEL); if (!dev->rawdescriptors) { err("out of memory"); - return -1; + return -ENOMEM; } for (cfgno = 0; cfgno < dev->descriptor.bNumConfigurations; cfgno++) { @@ -1751,8 +1744,10 @@ if (result < 8) { if (result < 0) err("unable to get descriptor"); - else + else { err("config descriptor too short (expected %i, got %i)", 8, result); + result = -EINVAL; + } goto err; } @@ -1776,6 +1771,7 @@ if (result < length) { err("config descriptor too short (expected %i, got %i)", length, result); + result = -EINVAL; kfree(bigbuffer); goto err; } @@ -1786,7 +1782,7 @@ if (result > 0) dbg("descriptor data left"); else if (result < 0) { - result = -1; + result = -EINVAL; goto err; } } @@ -1921,14 +1917,13 @@ return 1; } - dev->actconfig = dev->config; - usb_set_maxpacket(dev); - /* we set the default configuration here */ err = usb_set_configuration(dev, dev->config[0].bConfigurationValue); if (err) { err("failed to set default configuration (error=%d)", err); - return -1; + clear_bit(dev->devnum, &dev->bus->devmap.devicemap); + dev->devnum = -1; + return 1; } dbg("new device strings: Mfr=%d, Product=%d, SerialNumber=%d", @@ -2035,7 +2030,6 @@ EXPORT_SYMBOL(usb_interface_claimed); EXPORT_SYMBOL(usb_driver_release_interface); -EXPORT_SYMBOL(usb_init_root_hub); EXPORT_SYMBOL(usb_root_hub_string); EXPORT_SYMBOL(usb_new_device); EXPORT_SYMBOL(usb_reset_device); diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/usbkbd.c linux/drivers/usb/usbkbd.c --- v2.4.0-test5/linux/drivers/usb/usbkbd.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/usbkbd.c Thu Jul 27 18:36:54 2000 @@ -36,6 +36,7 @@ #include MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_DESCRIPTION("USB HID Boot Protocol keyboard driver"); static unsigned char usb_kbd_keycode[256] = { 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/usbmouse.c linux/drivers/usb/usbmouse.c --- v2.4.0-test5/linux/drivers/usb/usbmouse.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/usbmouse.c Thu Jul 27 18:36:54 2000 @@ -36,6 +36,7 @@ #include MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_DESCRIPTION("USB HID Boot Protocol mouse driver"); struct usb_mouse { signed char data[8]; diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/wacom.c linux/drivers/usb/wacom.c --- v2.4.0-test5/linux/drivers/usb/wacom.c Fri Jun 23 21:55:10 2000 +++ linux/drivers/usb/wacom.c Thu Jul 27 18:36:54 2000 @@ -51,6 +51,7 @@ #include MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_DESCRIPTION("USB Wacom Graphire and Wacom Intuos tablet driver"); /* * Wacom Graphire packet: diff -u --recursive --new-file v2.4.0-test5/linux/drivers/video/Config.in linux/drivers/video/Config.in --- v2.4.0-test5/linux/drivers/video/Config.in Mon Jul 10 16:47:25 2000 +++ linux/drivers/video/Config.in Wed Aug 9 14:11:11 2000 @@ -30,9 +30,7 @@ if [ "$CONFIG_ARCH_ACORN" = "y" ]; then bool ' Acorn VIDC support' CONFIG_FB_ACORN fi - if [ "$CONFIG_ARCH_NETWINDER" = "y" ]; then - tristate ' Cyber2000 support' CONFIG_FB_CYBER2000 - fi + tristate ' Cyber2000 support' CONFIG_FB_CYBER2000 if [ "$CONFIG_ARCH_SA1100" = "y" ]; then bool ' SA-1100 LCD support' CONFIG_FB_SA1100 fi @@ -64,14 +62,12 @@ fi if [ "$CONFIG_PPC" = "y" ]; then bool ' Open Firmware frame buffer device support' CONFIG_FB_OF - if [ "$CONFIG_FB_OF" = "y" ]; then - bool ' Apple "control" display support' CONFIG_FB_CONTROL - bool ' Apple "platinum" display support' CONFIG_FB_PLATINUM - bool ' Apple "valkyrie" display support' CONFIG_FB_VALKYRIE - bool ' IMS Twin Turbo display support' CONFIG_FB_IMSTT - bool ' Chips 65550 display support' CONFIG_FB_CT65550 - bool ' S3 Trio display support' CONFIG_FB_S3TRIO - fi + bool ' Apple "control" display support' CONFIG_FB_CONTROL + bool ' Apple "platinum" display support' CONFIG_FB_PLATINUM + bool ' Apple "valkyrie" display support' CONFIG_FB_VALKYRIE + bool ' Chips 65550 display support' CONFIG_FB_CT65550 + bool ' IMS Twin Turbo display support' CONFIG_FB_IMSTT + bool ' S3 Trio display support' CONFIG_FB_S3TRIO tristate ' VGA 16-color graphics console' CONFIG_FB_VGA16 fi if [ "$CONFIG_MAC" = "y" ]; then diff -u --recursive --new-file v2.4.0-test5/linux/drivers/video/Makefile linux/drivers/video/Makefile --- v2.4.0-test5/linux/drivers/video/Makefile Fri Jul 14 12:12:14 2000 +++ linux/drivers/video/Makefile Sun Aug 6 11:23:41 2000 @@ -10,8 +10,6 @@ O_TARGET := video.o O_OBJS := M_OBJS := -# This is a nice idea but needs depmod altering -# MOD_LIST_NAME := VIDEO_MODULES # All of the (potential) objects that export symbols. # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'. diff -u --recursive --new-file v2.4.0-test5/linux/drivers/video/S3triofb.c linux/drivers/video/S3triofb.c --- v2.4.0-test5/linux/drivers/video/S3triofb.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/video/S3triofb.c Fri Aug 4 18:06:34 2000 @@ -77,6 +77,7 @@ * Interface used by the world */ +static void __init s3triofb_of_init(struct device_node *dp); static int s3trio_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info); static int s3trio_get_var(struct fb_var_screeninfo *var, int con, @@ -263,12 +264,11 @@ int __init s3triofb_init(void) { -#ifdef __powerpc__ - /* We don't want to be called like this. */ - /* We rely on Open Firmware (offb) instead. */ -#else /* !__powerpc__ */ - /* To be merged with cybervision */ -#endif /* !__powerpc__ */ + struct device_node *dp; + + dp = find_devices("S3Trio"); + if (dp != 0) + s3triofb_of_init(dp); return 0; } @@ -376,10 +376,10 @@ * We heavily rely on OF for the moment. This needs fixing. */ -void __init s3triofb_init_of(struct device_node *dp) +static void __init s3triofb_of_init(struct device_node *dp) { int i, *pp, len; - unsigned long address; + unsigned long address, size; u_long *CursorBase; strncat(s3trio_name, dp->name, sizeof(s3trio_name)); @@ -416,9 +416,13 @@ fb_fix.line_length = fb_var.xres_virtual; fb_fix.smem_len = fb_fix.line_length*fb_var.yres; - s3trio_init(dp); address = 0xc6000000; - s3trio_base = ioremap(address,64*1024*1024); + size = 64*1024*1024; + if (!request_mem_region(address, size, "S3triofb")) + return; + + s3trio_init(dp); + s3trio_base = ioremap(address, size); fb_fix.smem_start = address; fb_fix.type = FB_TYPE_PACKED_PIXELS; fb_fix.type_aux = 0; @@ -693,12 +697,6 @@ else fb_set_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel), 1, s3trio_setcolreg, &fb_info); -} - -int s3triofb_setup(char *options) { - - return 0; - } static void Trio_WaitQueue(u_short fifo) { diff -u --recursive --new-file v2.4.0-test5/linux/drivers/video/acornfb.c linux/drivers/video/acornfb.c --- v2.4.0-test5/linux/drivers/video/acornfb.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/video/acornfb.c Wed Aug 9 14:11:11 2000 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -1532,8 +1533,8 @@ * set count to 1, and free * the page. */ - clear_bit(PG_reserved, &mem_map[MAP_NR(virtual_start)].flags); - atomic_set(&mem_map[MAP_NR(virtual_start)].count, 1); + mem_map_unreserve(virt_to_page(virtual_start)); + atomic_set(&virt_to_page(virtual_start)->count, 1); free_page(virtual_start); virtual_start += PAGE_SIZE; @@ -1628,7 +1629,7 @@ for (page = current_par.screen_base; page < PAGE_ALIGN(current_par.screen_base + size); page += PAGE_SIZE) - mem_map[MAP_NR(page)].flags |= (1 << PG_reserved); + mem_map_reserve(virt_to_page(page)); /* Hand back any excess pages that we allocated. */ for (page = current_par.screen_base + size; page < top; page += PAGE_SIZE) free_page(page); @@ -1662,8 +1663,12 @@ sizeof(modedb) / sizeof(*modedb), &acornfb_default_mode, DEFAULT_BPP); - if (!rc && fb_find_mode(&init_var, &fb_info, NULL, NULL, 0, - &acornfb_default_mode, DEFAULT_BPP)) { + /* + * If we didn't find an exact match, try the + * generic database. + */ + if (rc != 1 && fb_find_mode(&init_var, &fb_info, NULL, NULL, 0, + &acornfb_default_mode, DEFAULT_BPP)) { printk("Acornfb: no valid mode found\n"); } diff -u --recursive --new-file v2.4.0-test5/linux/drivers/video/chipsfb.c linux/drivers/video/chipsfb.c --- v2.4.0-test5/linux/drivers/video/chipsfb.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/video/chipsfb.c Fri Aug 4 18:06:34 2000 @@ -113,8 +113,8 @@ * Exported functions */ int chips_init(void); -void chips_of_init(struct device_node *dp); +static void chips_of_init(struct device_node *dp); static int chips_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info); static int chips_get_var(struct fb_var_screeninfo *var, int con, @@ -625,17 +625,15 @@ int __init chips_init(void) { -#ifndef CONFIG_FB_OF struct device_node *dp; dp = find_devices("chips65550"); if (dp != 0) chips_of_init(dp); -#endif /* CONFIG_FB_OF */ return 0; } -void __init chips_of_init(struct device_node *dp) +static void __init chips_of_init(struct device_node *dp) { struct fb_info_chips *p; unsigned long addr; @@ -649,6 +647,10 @@ return; memset(p, 0, sizeof(*p)); addr = dp->addrs[0].address; + if (!request_mem_region(addr, dp->addrs[0].size, "chipsfb")) { + kfree(p); + return; + } #ifdef __BIG_ENDIAN addr += 0x800000; // Use big-endian aperture #endif diff -u --recursive --new-file v2.4.0-test5/linux/drivers/video/clgenfb.c linux/drivers/video/clgenfb.c --- v2.4.0-test5/linux/drivers/video/clgenfb.c Thu Jul 27 17:38:01 2000 +++ linux/drivers/video/clgenfb.c Fri Aug 4 18:06:34 2000 @@ -56,9 +56,6 @@ #ifdef CONFIG_AMIGA #include #endif -#ifdef CONFIG_FB_OF -#include -#endif #include