diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-08-08 12:37:17 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-08-08 12:37:17 +0000 |
commit | 9aa9eb41942b918f385ccabd2efdd6e7e4232165 (patch) | |
tree | 20bec7da036d31ec185dfc1dcc00753c7ac9b170 | |
parent | 87075e049581f880f01eb0b41aa6ac807b299e35 (diff) |
Merge with Linux 2.4.0-test6-pre1.
196 files changed, 4033 insertions, 1894 deletions
@@ -1071,15 +1071,11 @@ D: Berkshire PC Watchdog Driver 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 @@ -1556,6 +1552,12 @@ S: 8786 Niwot Road 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 diff --git a/Documentation/DMA-mapping.txt b/Documentation/DMA-mapping.txt index 443d07be8..5dd11a173 100644 --- a/Documentation/DMA-mapping.txt +++ b/Documentation/DMA-mapping.txt @@ -111,7 +111,7 @@ There are two types of DMA mappings: - 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 @@ There are two types of DMA mappings: 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 @@ it from the CPU and dma_handle which you pass to the card. 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 @@ as you possibly can. 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 --git a/Documentation/IO-mapping.txt b/Documentation/IO-mapping.txt index b18355ba7..78253e5b1 100644 --- a/Documentation/IO-mapping.txt +++ b/Documentation/IO-mapping.txt @@ -176,7 +176,7 @@ ioremap() function "vremap()". ioremap() is the proper name, but I 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 --git a/Documentation/arm/SA1100/ThinClient b/Documentation/arm/SA1100/ThinClient index e3c8d5094..d5d7625fd 100644 --- a/Documentation/arm/SA1100/ThinClient +++ b/Documentation/arm/SA1100/ThinClient @@ -10,7 +10,7 @@ Current Linux support for this product has been provided by Nicolas Pitre <nico@cam.org>. 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 --git a/Documentation/arm/empeg/ir.txt b/Documentation/arm/empeg/ir.txt index c82e9c513..10a297450 100644 --- a/Documentation/arm/empeg/ir.txt +++ b/Documentation/arm/empeg/ir.txt @@ -17,7 +17,7 @@ For each of the 32 bits 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 --git a/Documentation/arm/nwfpe/README b/Documentation/arm/nwfpe/README index 253cea48c..771871de0 100644 --- a/Documentation/arm/nwfpe/README +++ b/Documentation/arm/nwfpe/README @@ -15,7 +15,7 @@ have attempted to use the C_SYMBOL_NAME macro wherever this may be 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 --git a/Documentation/cdrom/cdrom-standard.tex b/Documentation/cdrom/cdrom-standard.tex index 1bf6434cb..61becaf07 100644 --- a/Documentation/cdrom/cdrom-standard.tex +++ b/Documentation/cdrom/cdrom-standard.tex @@ -919,7 +919,7 @@ the current flags. 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 --git a/Documentation/cdrom/ide-cd b/Documentation/cdrom/ide-cd index b5967f506..8146e9987 100644 --- a/Documentation/cdrom/ide-cd +++ b/Documentation/cdrom/ide-cd @@ -286,7 +286,7 @@ b. Timeout/IRQ errors. 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 --git a/Documentation/computone.txt b/Documentation/computone.txt index 444d0c4f4..de281aa84 100644 --- a/Documentation/computone.txt +++ b/Documentation/computone.txt @@ -93,7 +93,7 @@ Previously, the driver sources were packaged with a set of patch files 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 @@ Higher speeds can be obtained using the setserial utility which remaps 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 @@ DEVFS is the DEVice File System available as an add on package for the 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 <http://www.atnf.csiro.au/~rgooch/linux/> 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 --git a/Documentation/cpqarray.txt b/Documentation/cpqarray.txt index 67db480cb..a2c9a0862 100644 --- a/Documentation/cpqarray.txt +++ b/Documentation/cpqarray.txt @@ -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 --git a/Documentation/fb/aty128fb.txt b/Documentation/fb/aty128fb.txt index c1c574b42..338256590 100644 --- a/Documentation/fb/aty128fb.txt +++ b/Documentation/fb/aty128fb.txt @@ -66,7 +66,7 @@ Limitations 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 <brad@neruo.com> diff --git a/Documentation/fb/matroxfb.txt b/Documentation/fb/matroxfb.txt index 2575ecf17..13a641b98 100644 --- a/Documentation/fb/matroxfb.txt +++ b/Documentation/fb/matroxfb.txt @@ -193,7 +193,7 @@ nocross4MB - pixel line must not cross 4MB boundary. It is default for 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 --git a/Documentation/fb/vesafb.txt b/Documentation/fb/vesafb.txt index 19d810a44..d7e7bd78c 100644 --- a/Documentation/fb/vesafb.txt +++ b/Documentation/fb/vesafb.txt @@ -62,7 +62,7 @@ So the table for the Kernel mode numbers are: 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 --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 421b17318..6213242da 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -137,7 +137,7 @@ bmap: yes 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 --git a/Documentation/filesystems/affs.txt b/Documentation/filesystems/affs.txt index 543b02a7c..30c973859 100644 --- a/Documentation/filesystems/affs.txt +++ b/Documentation/filesystems/affs.txt @@ -158,7 +158,7 @@ If you boot Windows 95 (don't know about 3.x, 98 and NT) while you 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 --git a/Documentation/filesystems/coda.txt b/Documentation/filesystems/coda.txt index 4ab793a71..613113560 100644 --- a/Documentation/filesystems/coda.txt +++ b/Documentation/filesystems/coda.txt @@ -1531,7 +1531,7 @@ kernel support. 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 @@ kernel support. 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 --git a/Documentation/filesystems/fat_cvf.txt b/Documentation/filesystems/fat_cvf.txt index c1cf27bd7..9082cbe4e 100644 --- a/Documentation/filesystems/fat_cvf.txt +++ b/Documentation/filesystems/fat_cvf.txt @@ -140,7 +140,7 @@ It contains... 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 --git a/Documentation/filesystems/hpfs.txt b/Documentation/filesystems/hpfs.txt index 756fcb2c0..ac2b1c6ae 100644 --- a/Documentation/filesystems/hpfs.txt +++ b/Documentation/filesystems/hpfs.txt @@ -25,14 +25,14 @@ conv=binary,text,auto (default binary) - 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 @@ access it under names 'a.', 'a..', 'a . . . ' etc. 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 @@ values doesn't work. 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 @@ file has a pointer to codepage it's name is in. However OS/2 was created in 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 @@ File names like "a .b" are marked as 'long' by OS/2 but chkdsk "corrects" it and 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 @@ History 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 --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index fef3bb743..c2314e0f1 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -1047,7 +1047,7 @@ low and the high value. 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 --git a/Documentation/filesystems/ufs.txt b/Documentation/filesystems/ufs.txt index dafae246d..0e2b243ff 100644 --- a/Documentation/filesystems/ufs.txt +++ b/Documentation/filesystems/ufs.txt @@ -9,7 +9,7 @@ UFS OPTIONS 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 --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 7d1f5ca72..9d91d1210 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -24,7 +24,7 @@ What is it? <section> 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 @@ A Quick Look At How It Works <section> 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 --git a/Documentation/floppy.txt b/Documentation/floppy.txt index 463937232..99d3ad3b3 100644 --- a/Documentation/floppy.txt +++ b/Documentation/floppy.txt @@ -88,7 +88,7 @@ insmod), first check whether there is a more recent version. 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 --git a/Documentation/highuid.txt b/Documentation/highuid.txt index ce7c17b7b..2c33926b9 100644 --- a/Documentation/highuid.txt +++ b/Documentation/highuid.txt @@ -20,7 +20,7 @@ What's left to be done for 32-bit UIDs on all Linux architectures: - 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 --git a/Documentation/i2c/dev-interface b/Documentation/i2c/dev-interface index 3a0f73bf6..03b5836f4 100644 --- a/Documentation/i2c/dev-interface +++ b/Documentation/i2c/dev-interface @@ -126,7 +126,7 @@ for details) through the following functions: __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 --git a/Documentation/i2c/i2c-protocol b/Documentation/i2c/i2c-protocol index d8cfdc77b..40c686d65 100644 --- a/Documentation/i2c/i2c-protocol +++ b/Documentation/i2c/i2c-protocol @@ -18,7 +18,7 @@ Count (8 bits): A data byte containing the length of a block operation. [..]: 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 @@ This corresponds to i2c_master_recv 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 @@ We have found some I2C devices that needs the following modifications: 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 --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients index a9328d869..a66debc0f 100644 --- a/Documentation/i2c/writing-clients +++ b/Documentation/i2c/writing-clients @@ -36,7 +36,7 @@ address. /* 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 @@ kernel booting is completed. 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 @@ SMBus communication 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 @@ Below all general purpose routines are listed, that were not mentioned 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 @@ The third, sixth and ninth parameters should always be NULL, and the 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 --git a/Documentation/ia64/README b/Documentation/ia64/README index 5bb41f96f..54b591caa 100644 --- a/Documentation/ia64/README +++ b/Documentation/ia64/README @@ -57,8 +57,8 @@ IA-64 SPECIFICS 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 Discontinuous large memory support; memory above 4GB will be + discontinuous 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 --git a/Documentation/ia64/efirtc.txt b/Documentation/ia64/efirtc.txt index b0c62765c..87f66bbaf 100644 --- a/Documentation/ia64/efirtc.txt +++ b/Documentation/ia64/efirtc.txt @@ -36,7 +36,7 @@ The Epoch is January 1st 1998. For backward compatibility reasons we don't 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 --git a/Documentation/isdn/00-INDEX b/Documentation/isdn/00-INDEX index b2e73cbc1..0f2b8e0f6 100644 --- a/Documentation/isdn/00-INDEX +++ b/Documentation/isdn/00-INDEX @@ -31,7 +31,7 @@ README.act2000 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 --git a/Documentation/isdn/INTERFACE.fax b/Documentation/isdn/INTERFACE.fax index 2c9659f0d..4c164b805 100644 --- a/Documentation/isdn/INTERFACE.fax +++ b/Documentation/isdn/INTERFACE.fax @@ -4,7 +4,7 @@ $Id: INTERFACE.fax,v 1.1 1999/08/11 20:30:28 armin Exp $ 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 @@ Structure T30_s: 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 --git a/Documentation/isdn/README b/Documentation/isdn/README index afd9f45af..0d3b0b023 100644 --- a/Documentation/isdn/README +++ b/Documentation/isdn/README @@ -146,7 +146,7 @@ README for the ISDN-subsystem 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 --git a/Documentation/isdn/README.HiSax b/Documentation/isdn/README.HiSax index 041678225..fb64b1ecd 100644 --- a/Documentation/isdn/README.HiSax +++ b/Documentation/isdn/README.HiSax @@ -77,7 +77,7 @@ Note: PCF, PCF-Pro: up to now, only the ISDN part is supported 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 @@ to e.g. the Internet: /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 @@ a) Use state of the art isdn4k-utils 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 --git a/Documentation/isdn/README.act2000 b/Documentation/isdn/README.act2000 index 7248ead80..0846d96b3 100644 --- a/Documentation/isdn/README.act2000 +++ b/Documentation/isdn/README.act2000 @@ -7,7 +7,7 @@ There are 3 Types of this card available. A ISA-, MCA-, and PCMCIA-Bus 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 --git a/Documentation/isdn/README.avmb1 b/Documentation/isdn/README.avmb1 index 6fa9406df..9e075484e 100644 --- a/Documentation/isdn/README.avmb1 +++ b/Documentation/isdn/README.avmb1 @@ -175,7 +175,7 @@ a mail to majordomo@calle.in-berlin.de with 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 --git a/Documentation/isdn/README.concap b/Documentation/isdn/README.concap index a934fe346..2f114babe 100644 --- a/Documentation/isdn/README.concap +++ b/Documentation/isdn/README.concap @@ -68,7 +68,7 @@ increased. 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 --git a/Documentation/isdn/README.diversion b/Documentation/isdn/README.diversion index 8e1d7a01b..98909b1bf 100644 --- a/Documentation/isdn/README.diversion +++ b/Documentation/isdn/README.diversion @@ -57,7 +57,7 @@ Table of contents 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 @@ Table of contents 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 --git a/Documentation/isdn/README.hysdn b/Documentation/isdn/README.hysdn index c9dbd0de8..9cfac4626 100644 --- a/Documentation/isdn/README.hysdn +++ b/Documentation/isdn/README.hysdn @@ -92,7 +92,7 @@ Table of contents 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 @@ Table of contents 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 --git a/Documentation/isdn/README.icn b/Documentation/isdn/README.icn index 9c72e6025..37aa7f3d0 100644 --- a/Documentation/isdn/README.icn +++ b/Documentation/isdn/README.icn @@ -139,7 +139,7 @@ Loading the firmware into the card: 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 --git a/Documentation/isdn/README.sc b/Documentation/isdn/README.sc index b70db7a63..1153cd926 100644 --- a/Documentation/isdn/README.sc +++ b/Documentation/isdn/README.sc @@ -93,7 +93,7 @@ include: 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 @@ A) 10 steps to the establishment of a basic HDLC connection 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 @@ B) Establishment of a PPP connection 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 @@ C) Establishment of a MLPPP connection 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 --git a/Documentation/joystick-api.txt b/Documentation/joystick-api.txt index b3a0c20c7..763a5c4ff 100644 --- a/Documentation/joystick-api.txt +++ b/Documentation/joystick-api.txt @@ -29,13 +29,13 @@ By default, the device is opened in blocking mode. 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 @@ JS_VERSION symbol ~~~~~~~~~~~~~~ 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 --git a/Documentation/joystick-parport.txt b/Documentation/joystick-parport.txt index 0576fc07e..fabfb1f01 100644 --- a/Documentation/joystick-parport.txt +++ b/Documentation/joystick-parport.txt @@ -22,7 +22,7 @@ connecting such devices. 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 @@ controllers: ~~~~~~~~ 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 --git a/Documentation/joystick.txt b/Documentation/joystick.txt index 18fc52232..e66fb0d85 100644 --- a/Documentation/joystick.txt +++ b/Documentation/joystick.txt @@ -166,7 +166,7 @@ other system. 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 @@ models, the additional buttons on the 'Plus' versions are not supported yet. 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 @@ but is not limited to: 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 --git a/Documentation/kbuild/commands.txt b/Documentation/kbuild/commands.txt index a73211848..d61e1a16e 100644 --- a/Documentation/kbuild/commands.txt +++ b/Documentation/kbuild/commands.txt @@ -84,7 +84,7 @@ Here are the targets available at the top level: 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 --git a/Documentation/kbuild/config-language.txt b/Documentation/kbuild/config-language.txt index b37dafb7e..dc1756013 100644 --- a/Documentation/kbuild/config-language.txt +++ b/Documentation/kbuild/config-language.txt @@ -80,7 +80,7 @@ Here are the basic grammar elements. 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 @@ Note that the bool verb does not have a default value. People keep 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 diff --git a/Documentation/m68k/README.buddha b/Documentation/m68k/README.buddha index d3b7bc73f..bf802ffc9 100644 --- a/Documentation/m68k/README.buddha +++ b/Documentation/m68k/README.buddha @@ -21,7 +21,7 @@ Rom-vector: $1000 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 @@ address is written to $4a, then the whole Byte is written to $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 @@ IRQ-lines of the IDE-ports by reading from the three (two 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 --git a/Documentation/m68k/kernel-options.txt b/Documentation/m68k/kernel-options.txt index 5938cb8cf..e191baad8 100644 --- a/Documentation/m68k/kernel-options.txt +++ b/Documentation/m68k/kernel-options.txt @@ -482,7 +482,7 @@ the physical linelength differs from the visible length. With ProMST, 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 --git a/Documentation/md.txt b/Documentation/md.txt index 7e894fd97..0df89447b 100644 --- a/Documentation/md.txt +++ b/Documentation/md.txt @@ -6,7 +6,7 @@ Tools that manage md devices can be found at 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=<md device no.>,<raid level>,<chunk size factor>,<fault level>,dev0,dev1,...,devn for raid arrays with persistant superblocks diff --git a/Documentation/moxa-smartio b/Documentation/moxa-smartio index 4357e6772..75efa6840 100644 --- a/Documentation/moxa-smartio +++ b/Documentation/moxa-smartio @@ -23,7 +23,7 @@ Content -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 @@ Content 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 @@ Content # 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 @@ Content # ./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 @@ Content 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 @@ Content 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 @@ Content ----------------------------------------------------------------------------- 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 @@ Content 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 --git a/Documentation/mtrr.txt b/Documentation/mtrr.txt index 941da7e91..013328363 100644 --- a/Documentation/mtrr.txt +++ b/Documentation/mtrr.txt @@ -31,7 +31,7 @@ Richard Gooch 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 @@ Removing MTRRs from the C-shell: 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 @@ Reading MTRRs from a C programme using ioctl()'s: */ /* - 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 --git a/Documentation/networking/README.sb1000 b/Documentation/networking/README.sb1000 index 37c39a0c8..f82d42584 100644 --- a/Documentation/networking/README.sb1000 +++ b/Documentation/networking/README.sb1000 @@ -30,7 +30,7 @@ cable modem easy. 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 --git a/Documentation/networking/comx.txt b/Documentation/networking/comx.txt index a58e78d90..38ad51622 100644 --- a/Documentation/networking/comx.txt +++ b/Documentation/networking/comx.txt @@ -63,7 +63,7 @@ values upon creation, so you don't necessarily have to change all of them. 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 --git a/Documentation/networking/cs89x0.txt b/Documentation/networking/cs89x0.txt index 24f15cb71..aaccf6bc0 100644 --- a/Documentation/networking/cs89x0.txt +++ b/Documentation/networking/cs89x0.txt @@ -214,7 +214,7 @@ Example: 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 @@ e) The minimum command-line configuration required if an EEPROM is 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 --git a/Documentation/networking/decnet.txt b/Documentation/networking/decnet.txt index 3a4116310..a2b050be9 100644 --- a/Documentation/networking/decnet.txt +++ b/Documentation/networking/decnet.txt @@ -44,7 +44,7 @@ The kernel command line takes options looking like the following: 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 --git a/Documentation/networking/dmfe.txt b/Documentation/networking/dmfe.txt index c8e561596..c0e839867 100644 --- a/Documentation/networking/dmfe.txt +++ b/Documentation/networking/dmfe.txt @@ -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 --git a/Documentation/networking/ethertap.txt b/Documentation/networking/ethertap.txt index 7af37a004..653f043a7 100644 --- a/Documentation/networking/ethertap.txt +++ b/Documentation/networking/ethertap.txt @@ -1,7 +1,7 @@ Documentation on setup and use of EtherTap. Contact Jay Schulist <jschlst@turbolinux.com> if you -have questions or need futher assistance. +have questions or need further assistance. Introduction ============ diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 482fbecb0..e1436a7bb 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -88,7 +88,7 @@ tcp_keepalive_interval - INTEGER 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 @@ tcp_max_orphans - INTEGER (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_stdurg - BOOLEAN 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 --git a/Documentation/networking/ipddp.txt b/Documentation/networking/ipddp.txt index 8df88a7df..5fb6c3c74 100644 --- a/Documentation/networking/ipddp.txt +++ b/Documentation/networking/ipddp.txt @@ -1,7 +1,7 @@ Text file for ipddp.c: AppleTalk-IP Decapsulation and AppleTalk-IP Encapsulation -This text file writen by Jay Schulist <jschlst@turbolinux.com> +This text file is written by Jay Schulist <jschlst@turbolinux.com> Introduction ------------ diff --git a/Documentation/networking/iphase.txt b/Documentation/networking/iphase.txt index 94356d67d..39ccb8595 100644 --- a/Documentation/networking/iphase.txt +++ b/Documentation/networking/iphase.txt @@ -137,7 +137,7 @@ Installation -Pcbr:max_pcr=<xxx> 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 --git a/Documentation/networking/olympic.txt b/Documentation/networking/olympic.txt index 04198aec5..63806258a 100644 --- a/Documentation/networking/olympic.txt +++ b/Documentation/networking/olympic.txt @@ -38,14 +38,14 @@ the driver now re-sizes buffers based on MTU settings as well. 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 @@ mode. All unexpected MAC frames (beaconing etc.) will be received 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 --git a/Documentation/networking/shaper.txt b/Documentation/networking/shaper.txt index 1be0db8c0..6c4ebb66a 100644 --- a/Documentation/networking/shaper.txt +++ b/Documentation/networking/shaper.txt @@ -42,7 +42,7 @@ multiple route tables to get the flexibility. 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 --git a/Documentation/networking/sis900.txt b/Documentation/networking/sis900.txt index b353eaa3b..6c26c9927 100644 --- a/Documentation/networking/sis900.txt +++ b/Documentation/networking/sis900.txt @@ -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 <http://ftp.kernel.org/pub/linux/kernel/> and its mirrors. The 1.06 diff --git a/Documentation/networking/sk98lin.txt b/Documentation/networking/sk98lin.txt index 510d2c4ef..2af3964ef 100644 --- a/Documentation/networking/sk98lin.txt +++ b/Documentation/networking/sk98lin.txt @@ -138,7 +138,7 @@ Insert a line of the form: 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 @@ which you set the parameter (A or B). 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 @@ which you set the parameter (A or B). 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 @@ it will simply drop them. 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 --git a/Documentation/networking/smctr.txt b/Documentation/networking/smctr.txt index 57dbe7a65..a393133a4 100644 --- a/Documentation/networking/smctr.txt +++ b/Documentation/networking/smctr.txt @@ -62,5 +62,5 @@ Errata: 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 --git a/Documentation/networking/tlan.txt b/Documentation/networking/tlan.txt index 901eb44bc..d513191cd 100644 --- a/Documentation/networking/tlan.txt +++ b/Documentation/networking/tlan.txt @@ -51,7 +51,7 @@ II. Driver Options 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 --git a/Documentation/networking/tms380tr.txt b/Documentation/networking/tms380tr.txt index f73895f4f..7ae835331 100644 --- a/Documentation/networking/tms380tr.txt +++ b/Documentation/networking/tms380tr.txt @@ -10,8 +10,8 @@ Please point your browser to: 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 @@ to http://www.syskonnect.com 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 --git a/Documentation/networking/tulip.txt b/Documentation/networking/tulip.txt index 35d5dea65..b5a625422 100644 --- a/Documentation/networking/tulip.txt +++ b/Documentation/networking/tulip.txt @@ -170,7 +170,7 @@ Version history 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 --git a/Documentation/networking/vortex.txt b/Documentation/networking/vortex.txt index 19d30079d..9a8039234 100644 --- a/Documentation/networking/vortex.txt +++ b/Documentation/networking/vortex.txt @@ -8,7 +8,7 @@ driver for Linux, 3c59x.c. The driver was written by Donald Becker <becker@cesdis.gsfc.nasa.gov> -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 <andrewm@uow.edu.au> @@ -64,7 +64,7 @@ its module is loaded. These are usually placed in /etc/modules.conf 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 @@ rx_copybreak=M 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 --git a/Documentation/networking/wan-router.txt b/Documentation/networking/wan-router.txt index f82ceb548..5cb1b3e42 100644 --- a/Documentation/networking/wan-router.txt +++ b/Documentation/networking/wan-router.txt @@ -142,11 +142,11 @@ REVISION HISTORY 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 --git a/Documentation/networking/wanpipe.txt b/Documentation/networking/wanpipe.txt index 7cb28178e..1fd1642d8 100644 --- a/Documentation/networking/wanpipe.txt +++ b/Documentation/networking/wanpipe.txt @@ -228,7 +228,7 @@ REVISION HISTORY 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 @@ REVISION HISTORY 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 --git a/Documentation/networking/wavelan.txt b/Documentation/networking/wavelan.txt index 82006e55d..c1acf5eb3 100644 --- a/Documentation/networking/wavelan.txt +++ b/Documentation/networking/wavelan.txt @@ -19,7 +19,7 @@ and many Linux driver to support it. 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 @@ Intel 82586 controler and a Lucent Modem, and is NOT 802.11 compliant. 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 --git a/Documentation/nmi_watchdog.txt b/Documentation/nmi_watchdog.txt index feb78559e..7f517608a 100644 --- a/Documentation/nmi_watchdog.txt +++ b/Documentation/nmi_watchdog.txt @@ -7,7 +7,7 @@ on Intel SMP hardware there is a feature that enables us to generate '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 --git a/Documentation/powerpc/SBC8260_memory_mapping.txt b/Documentation/powerpc/SBC8260_memory_mapping.txt index c61827c07..e6e9ee050 100644 --- a/Documentation/powerpc/SBC8260_memory_mapping.txt +++ b/Documentation/powerpc/SBC8260_memory_mapping.txt @@ -125,7 +125,7 @@ if you have questions, comments or corrections. 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 --git a/Documentation/s390/DASD b/Documentation/s390/DASD index 6f8f9b527..9963f1e9c 100644 --- a/Documentation/s390/DASD +++ b/Documentation/s390/DASD @@ -30,7 +30,7 @@ an Enterprise Storage Server (Seascape) should work fine as well. 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 @@ USAGE -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 --git a/Documentation/s390/cds.txt b/Documentation/s390/cds.txt index d126fe4d6..99d514d4c 100644 --- a/Documentation/s390/cds.txt +++ b/Documentation/s390/cds.txt @@ -778,7 +778,7 @@ flag : 0 (zero) or DOIO_WAIT_FOR_INTERRUPT 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 --git a/Documentation/sound/CMI8338 b/Documentation/sound/CMI8338 index 70423953c..ba3ca358b 100644 --- a/Documentation/sound/CMI8338 +++ b/Documentation/sound/CMI8338 @@ -14,7 +14,7 @@ WHAT'S NEW 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 --git a/Documentation/sound/ESS b/Documentation/sound/ESS index ac551fa4d..38d97ba97 100644 --- a/Documentation/sound/ESS +++ b/Documentation/sound/ESS @@ -12,7 +12,7 @@ Every chip that's detected as a later-than-es1688 chip has a 6 bits logarithmic 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 --git a/Documentation/sound/Introduction b/Documentation/sound/Introduction index f2ce25d67..86aa069c1 100644 --- a/Documentation/sound/Introduction +++ b/Documentation/sound/Introduction @@ -320,7 +320,7 @@ in the Sound-HOWTO). 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 @@ Module Loading: 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 --git a/Documentation/sound/Maestro b/Documentation/sound/Maestro index f572112ff..4a80eb3f8 100644 --- a/Documentation/sound/Maestro +++ b/Documentation/sound/Maestro @@ -70,7 +70,7 @@ maestro chip. 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 --git a/Documentation/sound/PSS b/Documentation/sound/PSS index ee81f7350..187b9525e 100644 --- a/Documentation/sound/PSS +++ b/Documentation/sound/PSS @@ -3,7 +3,7 @@ downloadable programs and also has an AD1848 "Microsoft Sound System" 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 --git a/Documentation/sound/README.OSS b/Documentation/sound/README.OSS index f594802e5..22c797926 100644 --- a/Documentation/sound/README.OSS +++ b/Documentation/sound/README.OSS @@ -81,7 +81,7 @@ contributors. (I could have forgotten some names.) 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 @@ Yamaha OPL3-SA1 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 @@ with ES688). 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 @@ At least a card called (Pearl?) Hypersound 16 supports IRQ 15 but it doesn't 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 --git a/Documentation/sound/README.modules b/Documentation/sound/README.modules index 39f7d954a..98f525cab 100644 --- a/Documentation/sound/README.modules +++ b/Documentation/sound/README.modules @@ -77,7 +77,7 @@ Persistent DMA Buffers: 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 --git a/Documentation/sound/README.ymfsb b/Documentation/sound/README.ymfsb index feda77915..af8a7d3a4 100644 --- a/Documentation/sound/README.ymfsb +++ b/Documentation/sound/README.ymfsb @@ -28,7 +28,7 @@ ABOUT THIS DRIVER 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 --git a/Documentation/stallion.txt b/Documentation/stallion.txt index 65f4bcb8a..084d485b1 100644 --- a/Documentation/stallion.txt +++ b/Documentation/stallion.txt @@ -62,7 +62,7 @@ configuration structure. Note that kernel PCI support is required to use PCI 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 @@ when loading the driver. The general form of the configuration argument is 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 --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt index 5fe4af170..cc447c1b5 100644 --- a/Documentation/sysctl/vm.txt +++ b/Documentation/sysctl/vm.txt @@ -118,11 +118,11 @@ freepages.min When the number of free pages in the system 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. ============================================================== @@ -198,7 +198,7 @@ In 2.2, the page cache is used for 3 main purposes: - 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 @@ each processor will be between the low and the high value. 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 --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt index 764392232..4bb08aaca 100644 --- a/Documentation/sysrq.txt +++ b/Documentation/sysrq.txt @@ -74,14 +74,14 @@ On other - If you know of the key combos for other architectures, please ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 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 --git a/Documentation/usb/CREDITS b/Documentation/usb/CREDITS index 38bdbaee0..e05f4d43f 100644 --- a/Documentation/usb/CREDITS +++ b/Documentation/usb/CREDITS @@ -45,7 +45,7 @@ THANKS file in Inaky's driver): - 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 @@ THANKS file in Inaky's driver): 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 @@ THANKS file in Inaky's driver): documentation for the UUSBD. Go for it! - Ric Klaren <ia_ric@cs.utwente.nl> for doing nice - introductory documents (compiting with Alberto's :). + introductory documents (competing with Alberto's :). - Christian Groessler <cpg@aladdin.de>, for it's help on those itchy bits ... :) @@ -143,7 +143,7 @@ THANKS file in Inaky's driver): - Rasca Gmelch <thron@gmx.de> has revived the raw driver and pointed bugs, as well as started the uusbd-utils package. - - Peter Dettori <dettori@ozy.dec.com> is unconvering bugs like + - Peter Dettori <dettori@ozy.dec.com> 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 @@ THANKS file in Inaky's driver): - 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 --git a/Documentation/usb/URB.txt b/Documentation/usb/URB.txt index 67cb9e31f..6cfd89ef3 100644 --- a/Documentation/usb/URB.txt +++ b/Documentation/usb/URB.txt @@ -23,7 +23,7 @@ usage and information passing to the completion handler. - URBs can be linked. After completing one URB, the next one can be automatically submitted. This is especially useful for ISO transfers: You only have read/write the data from/to the buffers in the completion -handler, the continous streaming itself is transparently done by the +handler, the continuous streaming itself is transparently done by the URB-machinery. 1.2. The URB structure @@ -104,7 +104,7 @@ transfer_flags. Usually, (to reduce restart time) the completion handler is called AFTER the URB re-submission. You can get the other way by setting -USB_URB_EARLY_COMPLETE in transfer_flags. This is implicite for +USB_URB_EARLY_COMPLETE in transfer_flags. This is implicit for INT transfers. 1.5. How to submit an URB? @@ -131,7 +131,7 @@ For isochronous endpoints, subsequent submitting of URBs to the same endpoint with the ASAP flag result in a seamless ISO streaming. Exception: The execution cannot be scheduled later than 900 frames from the 'now'-time. The same applies to INT transfers, but here the seamless continuation is -independent of the transfer flags (implicitely ASAP). +independent of the transfer flags (implicitly ASAP). 1.6. How to cancel an already running URB? @@ -174,14 +174,14 @@ It is allowed to specify a varying length from frame to frame (e.g. for audio synchronisation/adaptive transfer rates). You can also use the length 0 to omit one or more frames (striping). -As can be concluded from above, the UHCI-driver does not care for continous +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 --git a/Documentation/usb/input.txt b/Documentation/usb/input.txt index c60bd900b..079566472 100644 --- a/Documentation/usb/input.txt +++ b/Documentation/usb/input.txt @@ -134,7 +134,7 @@ instead. 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 @@ matter of a couple days to add it. 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 @@ And so on up to js31. ~~~~~~~~~~~~~ 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 @@ emulated, characters should appear if you move it. You can test the joystick emulation with the 'jstest' utility, available in the joystick package (see Documentation/joystick.txt). - You can test the event devics with the 'evtest' utitily available on the + 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 @@ struct input_event { }; '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 --git a/Documentation/usb/ohci.txt b/Documentation/usb/ohci.txt index 39a5ce482..ad2dbc6b8 100644 --- a/Documentation/usb/ohci.txt +++ b/Documentation/usb/ohci.txt @@ -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 @@ Features: - 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 --git a/Documentation/usb/ov511.txt b/Documentation/usb/ov511.txt index bd519ec07..b15e68176 100644 --- a/Documentation/usb/ov511.txt +++ b/Documentation/usb/ov511.txt @@ -158,7 +158,7 @@ MODULE PARAMETERS: 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 --git a/Documentation/usb/proc_usb_info.txt b/Documentation/usb/proc_usb_info.txt index 84510b950..f3e629cbe 100644 --- a/Documentation/usb/proc_usb_info.txt +++ b/Documentation/usb/proc_usb_info.txt @@ -103,7 +103,7 @@ S: Product=ssss 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 --git a/Documentation/usb/scanner.txt b/Documentation/usb/scanner.txt index e800b37e5..1dce956de 100644 --- a/Documentation/usb/scanner.txt +++ b/Documentation/usb/scanner.txt @@ -121,11 +121,11 @@ data in the file is raw data so it's not very useful for imaging. 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 --git a/Documentation/usb/uhci.txt b/Documentation/usb/uhci.txt index 53aaa11d8..13ed3a96c 100644 --- a/Documentation/usb/uhci.txt +++ b/Documentation/usb/uhci.txt @@ -32,7 +32,7 @@ The invention of the basic concept, and major coding were completed in two days (and nights) on the 16th and 17th of October 1999, now known as the great USB-October-Revolution started by GA, DF, and TS ;-) -Since the concept is in no way UHCI dependant, we hope that it will also be +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 @@ and its semantics were unnecessary complicated in our opinion. 1.4. What's really working? -As said above, CTRL und BULK already work fine even with the wrappers, +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 @@ before the End Chain QH (for BULK). Since only the QH->next pointers are affected, no atomic memory operation is required. The three QHs in the common chain are never equipped with TDs! -For ISO or INT, the TD for each frame is simply inserted into the apropriate +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 --git a/Documentation/usb/usb-serial.txt b/Documentation/usb/usb-serial.txt index b5b30911b..da7d19090 100644 --- a/Documentation/usb/usb-serial.txt +++ b/Documentation/usb/usb-serial.txt @@ -46,7 +46,7 @@ ConnectTech WhiteHEAT 4 port converter 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 --git a/Documentation/video4linux/CQcam.txt b/Documentation/video4linux/CQcam.txt index 6d54c07c0..8bbe61103 100644 --- a/Documentation/video4linux/CQcam.txt +++ b/Documentation/video4linux/CQcam.txt @@ -127,7 +127,7 @@ everything is working. 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 --git a/Documentation/video4linux/README.cpia b/Documentation/video4linux/README.cpia index 7ac342ff6..521ef795a 100644 --- a/Documentation/video4linux/README.cpia +++ b/Documentation/video4linux/README.cpia @@ -107,7 +107,7 @@ FEATURES: 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 @@ IMPLEMENTATION NOTES: 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 --git a/Documentation/video4linux/radiotrack.txt b/Documentation/video4linux/radiotrack.txt index a3f2347f0..2b75345f1 100644 --- a/Documentation/video4linux/radiotrack.txt +++ b/Documentation/video4linux/radiotrack.txt @@ -35,7 +35,7 @@ PHYSICAL DESCRIPTION -------------------- 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 --git a/Documentation/video4linux/zr36120.txt b/Documentation/video4linux/zr36120.txt index 54e46326a..96ecaa897 100644 --- a/Documentation/video4linux/zr36120.txt +++ b/Documentation/video4linux/zr36120.txt @@ -45,7 +45,7 @@ fps we ought to get... Here is the scenario: capturing frames 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 --git a/Documentation/vm/numa b/Documentation/vm/numa index 21a3442b7..b28fb352b 100644 --- a/Documentation/vm/numa +++ b/Documentation/vm/numa @@ -14,7 +14,7 @@ across nodes, and trying to house all the data structures that key components of the kernel need on memory on that node. Currently, all the numa support is to provide efficient handling -of widely discontiguous physical memory, so architectures which +of widely discontinuous physical memory, so architectures which are not NUMA but can have huge holes in the physical address space can use the same code. All this code is bracketed by CONFIG_DISCONTIGMEM. diff --git a/MAINTAINERS b/MAINTAINERS index a43577ded..f521bc0d5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -393,8 +393,8 @@ L: linux-kernel@vger.rutgers.edu 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 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 0 -EXTRAVERSION = -test5 +EXTRAVERSION = -test6-pre1 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) @@ -128,8 +128,8 @@ DRIVERS-y := 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 @@ -177,6 +177,8 @@ include arch/$(ARCH)/Makefile # use '-fno-strict-aliasing', but only if the compiler can take it CFLAGS += $(shell if $(CC) -fno-strict-aliasing -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-fno-strict-aliasing"; fi) +# likewise for -fno-delete-null-pointer-checks +CFLAGS += $(shell if $(CC) -fno-delete-null-pointer-checks -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-fno-delete-null-pointer-checks"; fi) export CPPFLAGS CFLAGS AFLAGS @@ -308,7 +310,7 @@ modules_install: MODLIB=$(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE); \ mkdir -p $$MODLIB; \ rm -f $$MODLIB/build; \ - ln -s $TOPDIR $$MODLIB/build; \ + ln -s $$TOPDIR $$MODLIB/build; \ cd modules; \ MODULES=""; \ inst_mod() { These="`cat $$1`"; MODULES="$$MODULES $$These"; \ diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index d77c2efc6..253b8d6c1 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -6,6 +6,7 @@ #include <linux/config.h> #include <asm/system.h> +#include <asm/cache.h> #define SIGCHLD 20 @@ -577,7 +578,7 @@ 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 + sll $3,L1_CACHE_SHIFT,$3 addq $3,$4,$4 ldq $4,0($4) sll $4,32,$3 diff --git a/arch/i386/Makefile b/arch/i386/Makefile index b63dcb89e..4087e089b 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile @@ -58,7 +58,7 @@ CFLAGS += $(shell if $(CC) -march=k6 -S -o /dev/null -xc /dev/null >/dev/null 2> 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 --git a/arch/i386/boot/compressed/misc.c b/arch/i386/boot/compressed/misc.c index 15d6e4f6a..abb382d8f 100644 --- a/arch/i386/boot/compressed/misc.c +++ b/arch/i386/boot/compressed/misc.c @@ -298,6 +298,7 @@ void setup_normal_output_buffer(void) 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 --git a/arch/i386/config.in b/arch/i386/config.in index d9fcd91db..5f6ae670d 100644 --- a/arch/i386/config.in +++ b/arch/i386/config.in @@ -344,5 +344,5 @@ mainmenu_option next_comment comment 'Kernel hacking' #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC -bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ +dep_bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ $CONFIG_VT endmenu diff --git a/arch/i386/defconfig b/arch/i386/defconfig index 1055ed5e3..4ead92e81 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -478,13 +478,13 @@ CONFIG_PSMOUSE=y # 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 --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c index 0519aee0c..c02385e79 100644 --- a/arch/i386/kernel/microcode.c +++ b/arch/i386/kernel/microcode.c @@ -145,11 +145,10 @@ static int microcode_open(struct inode *inode, struct file *file) return 0; } +/* our specific f_op->release() method needs no locking */ static int microcode_release(struct inode *inode, struct file *file) { - lock_kernel(); clear_bit(MICROCODE_IS_OPEN, µcode_status); - unlock_kernel(); return 0; } diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 085c48c8f..a83719fb7 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -23,7 +23,7 @@ obj- := 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 @@ else 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_SYNCLINK) += synclink.o 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 @@ else 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_977_WATCHDOG) += wdt977.o 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 @@ endif 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 @@ endif 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 --git a/drivers/char/drm/agpsupport.c b/drivers/char/drm/agpsupport.c index 628e8cad5..48a6aa5f9 100644 --- a/drivers/char/drm/agpsupport.c +++ b/drivers/char/drm/agpsupport.c @@ -30,6 +30,7 @@ #define __NO_VERSION__ #include "drmP.h" +#include <linux/module.h> drm_agp_func_t drm_agp = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; diff --git a/drivers/char/drm/auth.c b/drivers/char/drm/auth.c index 3ee85388e..9f81c5391 100644 --- a/drivers/char/drm/auth.c +++ b/drivers/char/drm/auth.c @@ -45,8 +45,6 @@ static drm_file_t *drm_find_file(drm_device_t *dev, drm_magic_t magic) 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 --git a/drivers/char/drm/drm_syms.c b/drivers/char/drm/drm_syms.c new file mode 100644 index 000000000..e7aaf569d --- /dev/null +++ b/drivers/char/drm/drm_syms.c @@ -0,0 +1,146 @@ +#include <linux/config.h> +#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 --git a/drivers/char/drm/memory.c b/drivers/char/drm/memory.c index e1f462bdd..5023de808 100644 --- a/drivers/char/drm/memory.c +++ b/drivers/char/drm/memory.c @@ -30,6 +30,7 @@ */ #define __NO_VERSION__ +#include <linux/config.h> #include "drmP.h" typedef struct drm_mem_stats { diff --git a/drivers/char/drm/r128_bufs.c b/drivers/char/drm/r128_bufs.c index d02fc5e00..bd81dcdc0 100644 --- a/drivers/char/drm/r128_bufs.c +++ b/drivers/char/drm/r128_bufs.c @@ -31,6 +31,7 @@ */ #define __NO_VERSION__ +#include <linux/config.h> #include "drmP.h" #include "r128_drv.h" #include "linux/un.h" diff --git a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c index 27b16614c..b382a13c5 100644 --- a/drivers/char/drm/r128_drv.c +++ b/drivers/char/drm/r128_drv.c @@ -466,8 +466,6 @@ int r128_open(struct inode *inode, struct file *filp) spin_unlock(&dev->count_lock); } - unlock_kernel(); - return retcode; } diff --git a/drivers/char/drm/tdfx_drv.c b/drivers/char/drm/tdfx_drv.c index 85f88044d..896705e97 100644 --- a/drivers/char/drm/tdfx_drv.c +++ b/drivers/char/drm/tdfx_drv.c @@ -446,9 +446,11 @@ int tdfx_release(struct inode *inode, struct file *filp) 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 --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 0e9d7b57f..6f4ebe44c 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -1154,9 +1154,7 @@ static ssize_t write_chan(struct tty_struct * tty, struct file * file, 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 @@ static ssize_t write_chan(struct tty_struct * tty, struct file * file, 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 --git a/drivers/i2c/Config.in b/drivers/i2c/Config.in index 9050f3528..405121edc 100644 --- a/drivers/i2c/Config.in +++ b/drivers/i2c/Config.in @@ -10,7 +10,7 @@ if [ "$CONFIG_I2C" != "n" ]; then 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 --git a/drivers/ide/pdc202xx.c b/drivers/ide/pdc202xx.c index 6385cd81b..72dd50134 100644 --- a/drivers/ide/pdc202xx.c +++ b/drivers/ide/pdc202xx.c @@ -862,7 +862,6 @@ void __init ide_init_pdc202xx (ide_hwif_t *hwif) (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 --git a/drivers/net/acenic.c b/drivers/net/acenic.c index 29d5d7638..ae023616a 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -607,6 +607,7 @@ MODULE_PARM(max_tx_desc, "1-" __MODULE_STRING(8) "i"); 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 @@ void __exit ace_module_cleanup(void) root_dev = next; } } -#endif int __init ace_module_init(void) diff --git a/drivers/net/gmac.c b/drivers/net/gmac.c index 4717a652c..17d328294 100644 --- a/drivers/net/gmac.c +++ b/drivers/net/gmac.c @@ -9,8 +9,6 @@ */ #include <linux/module.h> - -#include <linux/config.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/types.h> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 1d5efdfc4..8d0d245b3 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -223,6 +223,18 @@ static void __init quirk_piix3usb(struct pci_dev *dev) } /* + * 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 @@ static struct pci_fixup pci_fixups[] __initdata = { /* * 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 @@ static struct pci_fixup pci_fixups[] __initdata = { { 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 --git a/drivers/scsi/README.ibmmca b/drivers/scsi/README.ibmmca index 61fd18e51..313690c26 100644 --- a/drivers/scsi/README.ibmmca +++ b/drivers/scsi/README.ibmmca @@ -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 <langa2@kph.uni-mainz.de> 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 --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c index 393cf909e..aa4cca390 100644 --- a/drivers/scsi/ibmmca.c +++ b/drivers/scsi/ibmmca.c @@ -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 <linux/module.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/ctype.h> @@ -31,8 +34,13 @@ #include <linux/stat.h> #include <linux/mca.h> #include <asm/system.h> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,17) #include <linux/spinlock.h> +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) +#include <asm/spinlock.h> +#endif #include <asm/io.h> +#include <linux/init.h> #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 @@ struct im_scb 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 @@ struct im_sge 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 @@ struct im_sge #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 @@ struct im_sge #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 @@ struct im_tsb }; /*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 @@ struct im_tsb #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 @@ struct im_tsb 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 @@ struct subsys_list_struct 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 logical_device 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 @@ struct Driver_Statistics 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 Driver_Statistics 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 @@ struct ibmmca_hostdata 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 @@ struct ibmmca_hostdata #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 @@ struct ibmmca_hostdata #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 @@ struct ibmmca_hostdata 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 <linux/module.h> +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 @@ static char ibm_ansi_order = 0; /******************* 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 @@ static void do_interrupt_handler (int irq, void *dev_id, struct pt_regs *regs) 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 @@ static void interrupt_handler (int irq, void *dev_id, struct pt_regs *regs) 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 @@ static void interrupt_handler (int irq, void *dev_id, struct pt_regs *regs) 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 (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 (!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 (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)) + 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) { - 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); + 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 @@ static void interrupt_handler (int irq, void *dev_id, struct pt_regs *regs) 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 @@ static void interrupt_handler (int irq, void *dev_id, struct pt_regs *regs) } 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 @@ static void interrupt_handler (int irq, void *dev_id, struct pt_regs *regs) 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 @@ static void interrupt_handler (int irq, void *dev_id, struct pt_regs *regs) } /* 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 issue_cmd (int host_index, unsigned long cmd_reg, 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 @@ static int read_capacity(int host_index, int ldn) 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 @@ static int read_capacity(int host_index, int ldn) 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 @@ static int read_capacity(int host_index, int ldn) 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 @@ static int immediate_reset(int host_index, unsigned int ldn) 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 @@ static int immediate_reset(int host_index, unsigned int ldn) 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 @@ static char *ti_l(int value) { 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 @@ static char *ti_l(int value) 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 @@ static void check_devices (int host_index) 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; ldn++) { + probe_display(1); #ifdef IM_DEBUG_PROBE printk("."); #endif @@ -1068,14 +1533,20 @@ static void check_devices (int host_index) } lun = 0; /* default lun is 0 */ - + /* STEP 2: */ - printk("\nIBM MCA SCSI: Probing SCSI-devices."); - for (id=0; id<8; id++) + printk("\nIBM MCA SCSI: Probing SCSI-devices"); +#ifndef IM_DEBUG_PROBE + printk(" (this can take up to 2 minutes)"); +#endif + printk("."); + + for (id=0; id<max_pun ; id++) #ifdef CONFIG_SCSI_MULTI_LUN for (lun=0; lun<8; lun++) #endif { + probe_display(1); #ifdef IM_DEBUG_PROBE printk("."); #endif @@ -1095,31 +1566,32 @@ static void check_devices (int host_index) immediate_assign(host_index,id,lun,PROBE_LDN,REMOVE_LDN); } } - - /* STEP 3: */ + + /* STEP 3: */ printk("\nIBM MCA SCSI: Mapping SCSI-devices."); - + ldn = 0; lun = 0; - -#ifdef CONFIG_SCSI_MULTI_LUN + +#ifdef CONFIG_SCSI_MULTI_LUN for (lun=0; lun<8 && ldn<MAX_LOG_DEV; lun++) #endif - for (id=0; id<8 && ldn<MAX_LOG_DEV; id++) + for (id=0; id<max_pun && ldn<MAX_LOG_DEV; id++) { + probe_display(1); #ifdef IM_DEBUG_PROBE printk("."); #endif if (id != subsystem_pun(host_index)) { - if (get_scsi(host_index)[id][lun] != TYPE_NO_LUN && + if (get_scsi(host_index)[id][lun] != TYPE_NO_LUN && get_scsi(host_index)[id][lun] != TYPE_NO_DEVICE) { - /* Only map if accepted type. Always enter for + /* Only map if accepted type. Always enter for lun == 0 to get no gaps into ldn-mapping for ldn<7. */ immediate_assign(host_index,id,lun,ldn,SET_LDN); get_ldn(host_index)[id][lun]=ldn; /* map ldn */ - if (device_exists (host_index, ldn, + if (device_exists (host_index, ldn, &ld(host_index)[ldn].block_length, &ld(host_index)[ldn].device_type)) { @@ -1149,18 +1621,19 @@ static void check_devices (int host_index) get_ldn(host_index)[id][lun]=ldn; /* map ldn */ ldn++; } - } + } } - + /* STEP 4: */ - + /* map remaining ldns to non-existing devices */ for (lun=1; lun<8 && ldn<MAX_LOG_DEV; lun++) - for (id=0; id<8 && ldn<MAX_LOG_DEV; id++) + for (id=0; id<max_pun && ldn<MAX_LOG_DEV; id++) { if (get_scsi(host_index)[id][lun] == TYPE_NO_LUN || get_scsi(host_index)[id][lun] == TYPE_NO_DEVICE) { + probe_display(1); /* Map remaining ldns only to NON-existing pun,lun combinations to make sure an inquiry will fail. For MULTI_LUN, it is needed to avoid adapter autonome @@ -1169,20 +1642,20 @@ static void check_devices (int host_index) get_ldn(host_index)[id][lun]=ldn; ldn++; } - } - + } + printk("\n"); if (ibm_ansi_order) printk("IBM MCA SCSI: Device order: IBM/ANSI (pun=7 is first).\n"); else printk("IBM MCA SCSI: Device order: New Industry Standard (pun=0 is first).\n"); - + #ifdef IM_DEBUG_PROBE /* Show the physical and logical mapping during boot. */ printk("IBM MCA SCSI: Determined SCSI-device-mapping:\n"); printk(" Physical SCSI-Device Map Logical SCSI-Device Map\n"); printk("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<8; id++) + for (id=0; id<max_pun; id++) { printk("%2d ",id); for (lun=0; lun<8; lun++) @@ -1193,52 +1666,54 @@ static void check_devices (int host_index) printk("\n"); } #endif - + /* assign total number of found SCSI-devices to the statistics struct */ IBM_DS(host_index).total_scsi_devices = count_devices; - + /* decide for output in /proc-filesystem, if the configuration of SCSI-devices makes dynamical reassignment of devices necessary */ - if (count_devices>=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 @@ static int device_exists (int host_index, int ldn, int *block_length, *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 @@ static int device_exists (int host_index, int ldn, int *block_length, 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 @@ void ibmmca_scsi_setup (char *str, int *ints) } 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 @@ void ibmmca_scsi_setup (char *str, int *ints) 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 @@ static int ibmmca_getinfo (char *buf, int slot, void *dev) 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 @@ static int ibmmca_getinfo (char *buf, int slot, void *dev) } /* 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 @@ static int ibmmca_getinfo (char *buf, int slot, void *dev) } 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 @@ int ibmmca_detect (Scsi_Host_Template * scsi_template) 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 @@ int ibmmca_detect (Scsi_Host_Template * scsi_template) * 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 @@ int ibmmca_detect (Scsi_Host_Template * scsi_template) 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 @@ int ibmmca_detect (Scsi_Host_Template * scsi_template) 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 @@ int ibmmca_detect (Scsi_Host_Template * scsi_template) /* 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 @@ int ibmmca_detect (Scsi_Host_Template * scsi_template) 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 @@ ibmmca_register(Scsi_Host_Template * scsi_template, int port, int id, 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 @@ ibmmca_register(Scsi_Host_Template * scsi_template, int port, int id, 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 @@ ibmmca_register(Scsi_Host_Template * scsi_template, int port, int id, 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 @@ int ibmmca_release(struct Scsi_Host *shpnt) /*--------------------------------------------------------------------*/ /* 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 ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) 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 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) 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 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) 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; id<max_pun; id ++) for (lun=0; lun<8; lun++) { if (get_ldn(host_index)[id][lun] == next_ldn(host_index)) { - get_ldn(host_index)[id][lun] = TYPE_NO_DEVICE; + get_ldn(host_index)[id][lun] = TYPE_NO_DEVICE; /* unmap entry */ } } @@ -1808,66 +2478,69 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) /* change ldn to the right value, that is now next_ldn */ ldn = next_ldn(host_index); /* get device information for ld[ldn] */ - if (device_exists (host_index, ldn, + if (device_exists (host_index, ldn, &ld(host_index)[ldn].block_length, &ld(host_index)[ldn].device_type)) { ld(host_index)[ldn].cmd = 0; /* To prevent panic set 0, because devices that were not assigned, should have nothing in progress. */ - + /* increase assignment counters for statistics in /proc */ IBM_DS(host_index).dynamical_assignments++; IBM_DS(host_index).ldn_assignments[ldn]++; } else - /* panic here, because a device, found at boottime has + /* panic here, because a device, found at boottime has vanished */ panic("IBM MCA SCSI: ldn=0x%x, SCSI-device on (%d,%d) vanished!\n", ldn, target, cmd->lun); - + /* 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 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) 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 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) 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 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) 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 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) 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 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) 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 @@ int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) 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 @@ int ibmmca_abort (Scsi_Cmnd * cmd) /* 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 @@ int ibmmca_abort (Scsi_Cmnd * cmd) /*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 @@ int ibmmca_abort (Scsi_Cmnd * cmd) { 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 @@ int ibmmca_abort (Scsi_Cmnd * cmd) 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 @@ int ibmmca_abort (Scsi_Cmnd * cmd) 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 @@ int ibmmca_reset (Scsi_Cmnd * cmd, unsigned int reset_flags) 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 @@ int ibmmca_reset (Scsi_Cmnd * cmd, unsigned int reset_flags) { /* 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 @@ int ibmmca_reset (Scsi_Cmnd * cmd, unsigned int reset_flags) 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 @@ int ibmmca_reset (Scsi_Cmnd * cmd, unsigned int reset_flags) { 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 @@ int ibmmca_reset (Scsi_Cmnd * cmd, unsigned int reset_flags) 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 @@ int ibmmca_reset (Scsi_Cmnd * cmd, unsigned int reset_flags) 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 @@ int ibmmca_reset (Scsi_Cmnd * cmd, unsigned int reset_flags) { 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 @@ static int ldn_access_total_read_write(int host_index) { 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 @@ static int ldn_access_total_inquiry(int host_index) { 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 @@ static int ldn_access_total_modeselect(int host_index) { 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 ibmmca_proc_info (char *buffer, char **start, off_t offset, int length, 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 @@ int ibmmca_proc_info (char *buffer, char **start, off_t offset, int length, (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 @@ int ibmmca_proc_info (char *buffer, char **start, off_t offset, int length, 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 @@ int ibmmca_proc_info (char *buffer, char **start, off_t offset, int length, 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<max_pun; id++) { len += sprintf(buffer+len, " %2d ",id); for (lun=0; lun<8; lun++) - len += sprintf(buffer+len,"%2s ",ti_p(get_scsi(host_index)[id][lun])); - + len += sprintf(buffer+len,"%2s ",ti_p(get_scsi(host_index)[id][lun])); len += sprintf(buffer+len, " %2d ",id); for (lun=0; lun<8; lun++) len += sprintf(buffer+len,"%2s ",ti_l(get_ldn(host_index)[id][lun])); len += sprintf(buffer+len,"\n"); } - + len += sprintf(buffer+len, "(A = IBM-Subsystem, D = Harddisk, T = Tapedrive, P = Processor, W = WORM,\n"); len += sprintf(buffer+len, " R = CD-ROM, S = Scanner, M = MO-Drive, C = Medium-Changer, + = unprovided LUN,\n"); len += sprintf(buffer+len, " - = nothing found, nothing assigned or unprobed LUN)\n\n"); - + *start = buffer + offset; len -= offset; - if (len > 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 --git a/drivers/scsi/ibmmca.h b/drivers/scsi/ibmmca.h index 99d0fe90f..52cd7386b 100644 --- a/drivers/scsi/ibmmca.h +++ b/drivers/scsi/ibmmca.h @@ -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 <linux/version.h> #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_reset (Scsi_Cmnd *, unsigned int); 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 @@ extern int ibmmca_biosparam (Disk *, kdev_t, int *); 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 --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 3494e793e..10b65fa2d 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -1912,7 +1912,7 @@ out: * 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 --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 4ac3dbcfb..cc5bb1c48 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -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 @@ -1890,9 +1890,9 @@ static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size) 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 @@ static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size) 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 @@ static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size) 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 @@ static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp) 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 Sg_fd * sg_add_sfp(Sg_device * sdp, int dev) } 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 --git a/drivers/sound/Makefile b/drivers/sound/Makefile index 399148c74..2c7dbb018 100644 --- a/drivers/sound/Makefile +++ b/drivers/sound/Makefile @@ -62,7 +62,7 @@ obj-$(CONFIG_SOUND_VMIDI) += v_midi.o obj-$(CONFIG_SOUND_VIDC) += vidc_mod.o obj-$(CONFIG_SOUND_WAVEARTIST) += waveartist.o obj-$(CONFIG_SOUND_SGALAXY) += sgalaxy.o ad1848.o -obj-$(CONFIG_SOUND_AD1816) += ad1816.o +obj-$(CONFIG_SOUND_AD1816) += ad1816.o sound.o obj-$(CONFIG_SOUND_ACI_MIXER) += aci.o obj-$(CONFIG_SOUND_AWE32_SYNTH) += awe_wave.o diff --git a/drivers/usb/acm.c b/drivers/usb/acm.c index b60733b4a..49f881a8c 100644 --- a/drivers/usb/acm.c +++ b/drivers/usb/acm.c @@ -689,3 +689,6 @@ static void __exit acm_exit(void) 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 --git a/drivers/usb/audio.c b/drivers/usb/audio.c index 4560ad602..5d6def562 100644 --- a/drivers/usb/audio.c +++ b/drivers/usb/audio.c @@ -3732,4 +3732,6 @@ void cleanup_module(void) usb_deregister(&usb_audio_driver); } +MODULE_AUTHOR("Alan Cox <alan@lxorguk.ukuu.org.uk>, Thomas Sailer (sailer@ife.ee.ethz.ch)"); +MODULE_DESCRIPTION("USB Audio Class driver"); #endif diff --git a/drivers/usb/dabusb.c b/drivers/usb/dabusb.c index 7b19729a9..d04d3eaaa 100644 --- a/drivers/usb/dabusb.c +++ b/drivers/usb/dabusb.c @@ -841,6 +841,7 @@ void __exit dabusb_cleanup (void) 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 --git a/drivers/usb/dsbr100.c b/drivers/usb/dsbr100.c index e2056a2e3..6ffffdc6f 100644 --- a/drivers/usb/dsbr100.c +++ b/drivers/usb/dsbr100.c @@ -347,6 +347,9 @@ void cleanup_module(void) usb_deregister(&usb_dsbr100_driver); } +MODULE_AUTHOR("Markus Demleitner <msdemlei@tucana.harvard.edu>"); +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 --git a/drivers/usb/evdev.c b/drivers/usb/evdev.c index e11327cef..65109e9ca 100644 --- a/drivers/usb/evdev.c +++ b/drivers/usb/evdev.c @@ -351,3 +351,6 @@ static void __exit evdev_exit(void) module_init(evdev_init); module_exit(evdev_exit); + +MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); +MODULE_DESCRIPTION("Event character device driver"); diff --git a/drivers/usb/hid.c b/drivers/usb/hid.c index ae529b746..68a981e27 100644 --- a/drivers/usb/hid.c +++ b/drivers/usb/hid.c @@ -1524,3 +1524,6 @@ static void __exit hid_exit(void) module_init(hid_init); module_exit(hid_exit); + +MODULE_AUTHOR("Andreas Gal, Vojtech Pavlik <vojtech@suse.cz>"); +MODULE_DESCRIPTION("USB HID support drivers"); diff --git a/drivers/usb/ibmcam.c b/drivers/usb/ibmcam.c index d70c99ddf..6b85a15f0 100644 --- a/drivers/usb/ibmcam.c +++ b/drivers/usb/ibmcam.c @@ -127,21 +127,36 @@ static int init_model2_sat = -1; 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"); diff --git a/drivers/usb/iforce.c b/drivers/usb/iforce.c index a61b7801f..d70bfd90e 100644 --- a/drivers/usb/iforce.c +++ b/drivers/usb/iforce.c @@ -38,6 +38,7 @@ #include <linux/config.h> MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); +MODULE_DESCRIPTION("USB/RS232 I-Force joysticks and wheels driver"); #define USB_VENDOR_ID_LOGITECH 0x046d #define USB_DEVICE_ID_LOGITECH_WMFORCE 0xc281 diff --git a/drivers/usb/input.c b/drivers/usb/input.c index 98f1a1109..f3701965e 100644 --- a/drivers/usb/input.c +++ b/drivers/usb/input.c @@ -34,6 +34,7 @@ #include <linux/random.h> MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); +MODULE_DESCRIPTION("Input layer module"); EXPORT_SYMBOL(input_register_device); EXPORT_SYMBOL(input_unregister_device); diff --git a/drivers/usb/joydev.c b/drivers/usb/joydev.c index 2210ad0d1..99b17a3cd 100644 --- a/drivers/usb/joydev.c +++ b/drivers/usb/joydev.c @@ -83,6 +83,7 @@ struct joydev_list { static struct joydev *joydev_table[JOYDEV_MINORS]; MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); +MODULE_DESCRIPTION("Joystick device driver"); MODULE_SUPPORTED_DEVICE("input/js"); static int joydev_correct(int value, struct js_corr *corr) diff --git a/drivers/usb/keybdev.c b/drivers/usb/keybdev.c index 76496349b..95fce5e80 100644 --- a/drivers/usb/keybdev.c +++ b/drivers/usb/keybdev.c @@ -195,3 +195,6 @@ static void __exit keybdev_exit(void) module_init(keybdev_init); module_exit(keybdev_exit); + +MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); +MODULE_DESCRIPTION("Input driver to keyboard driver binding"); diff --git a/drivers/usb/microtek.c b/drivers/usb/microtek.c index a3de2b732..b8eb74c77 100644 --- a/drivers/usb/microtek.c +++ b/drivers/usb/microtek.c @@ -1050,3 +1050,6 @@ void __exit microtek_drv_exit(void) module_init(microtek_drv_init); module_exit(microtek_drv_exit); + +MODULE_AUTHOR("John Fremlin <vii@penguinpowered.com>, Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de>"); +MODULE_DESCRIPTION("Microtek Scanmaker X6 USB scanner driver"); diff --git a/drivers/usb/mousedev.c b/drivers/usb/mousedev.c index ea5ad301b..ccb118520 100644 --- a/drivers/usb/mousedev.c +++ b/drivers/usb/mousedev.c @@ -481,3 +481,6 @@ static void __exit mousedev_exit(void) module_init(mousedev_init); module_exit(mousedev_exit); + +MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); +MODULE_DESCRIPTION("Input driver to PS/2 or ImPS/2 device driver"); diff --git a/drivers/usb/ov511.c b/drivers/usb/ov511.c index 462a49957..73e3a5be1 100644 --- a/drivers/usb/ov511.c +++ b/drivers/usb/ov511.c @@ -108,16 +108,27 @@ static int cams = 1; 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 <mmcclelland@delphi.com> & Bret Wallach & Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha <cpbotha@ieee.org> & Claudio Matsuoka <claudio@conectiva.com>"); MODULE_DESCRIPTION("OV511 USB Camera Driver"); diff --git a/drivers/usb/pegasus.c b/drivers/usb/pegasus.c index 8c588f79e..0a264faaf 100644 --- a/drivers/usb/pegasus.c +++ b/drivers/usb/pegasus.c @@ -103,7 +103,7 @@ static int multicast_filter_limit = 32; MODULE_AUTHOR("Petko Manolov <petkan@spct.net>"); 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 --git a/drivers/usb/printer.c b/drivers/usb/printer.c index 987f1a8b5..96fa971d8 100644 --- a/drivers/usb/printer.c +++ b/drivers/usb/printer.c @@ -527,3 +527,6 @@ static void __exit usblp_exit(void) 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 --git a/drivers/usb/rio500.c b/drivers/usb/rio500.c index 011f853f6..c84a01fa6 100644 --- a/drivers/usb/rio500.c +++ b/drivers/usb/rio500.c @@ -445,3 +445,5 @@ void usb_rio_cleanup(void) module_init(usb_rio_init); module_exit(usb_rio_cleanup); +MODULE_AUTHOR("Cesar Miquel <miquel@df.uba.ar>"); +MODULE_DESCRIPTION("USB Rio 500 driver"); diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 146090ab2..31f913ff9 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -14,13 +14,7 @@ obj-m := 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 --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 9ecd1370b..c5c403b2b 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -1768,4 +1768,6 @@ void digi_exit (void) module_init(digi_init); module_exit(digi_exit); +MODULE_AUTHOR("Peter Berger <pberger@brimson.com>, Al Borchers <borchers@steinerpoint.com>"); +MODULE_DESCRIPTION("Digi AccelePort USB-4 Serial Converter driver"); diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index f78ff752b..aa156ba8d 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -741,3 +741,5 @@ void ftdi_sio_exit (void) module_init(ftdi_sio_init); module_exit(ftdi_sio_exit); +MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>"); +MODULE_DESCRIPTION("USB FTDI SIO driver"); diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 2fecdca12..64a1f709e 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -721,3 +721,5 @@ void keyspan_exit (void) module_init(keyspan_init); module_exit(keyspan_exit); +MODULE_AUTHOR("Hugh Blemings <hugh@linuxcare.com>"); +MODULE_DESCRIPTION("Keyspan USB to Serial Converter driver"); diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index aca2a38c5..675764ad4 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -720,3 +720,5 @@ void keyspan_pda_exit (void) module_init(keyspan_pda_init); module_exit(keyspan_pda_exit); +MODULE_AUTHOR("Brian Warner <warner@lothar.com>"); +MODULE_DESCRIPTION("USB Keyspan PDA Converter driver"); diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index f8145c37f..568f2b5cd 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -434,3 +434,5 @@ void visor_exit (void) module_init(visor_init); module_exit(visor_exit); +MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>"); +MODULE_DESCRIPTION("USB HandSpring Visor driver"); diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index a6ca6ebcb..7ec405501 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -549,3 +549,5 @@ void whiteheat_exit (void) module_init(whiteheat_init); module_exit(whiteheat_exit); +MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>"); +MODULE_DESCRIPTION("USB ConnectTech WhiteHEAT driver"); diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index aaf1072db..1b204ab28 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -12,18 +12,19 @@ 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 --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 21fe3ec97..25328669b 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -1,7 +1,7 @@ /* 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.6 2000/07/25 23:04:47 mdharm Exp $ * * Current development and maintainance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -49,21 +49,6 @@ #include <linux/malloc.h> -/* 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 --git a/drivers/usb/storage/scsiglue.h b/drivers/usb/storage/scsiglue.h index e9da1bcc0..f81787678 100644 --- a/drivers/usb/storage/scsiglue.h +++ b/drivers/usb/storage/scsiglue.h @@ -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 --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c new file mode 100644 index 000000000..275712961 --- /dev/null +++ b/drivers/usb/storage/sddr09.c @@ -0,0 +1,635 @@ +/* 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 <linux/sched.h> +#include <linux/errno.h> +#include <linux/malloc.h> + +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 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 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 sddr09_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 = sddr09_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<len && i<48; i++) { + sprintf(string+strlen(string), "%02X ", + data[i]); + if ((i%16)==15) { + US_DEBUGP("%s\n", string); + string[0] = 0; + } + } + if (string[0]!=0) + US_DEBUGP("%s\n", string); + } + } + + + US_DEBUGP("SCM data %s transfer %d sg buffers %d\n", + ( direction==SCSI_DATA_READ ? "in" : "out"), + len, use_sg); + + if (!use_sg) + result = sddr09_raw_bulk(us, direction, data, len); + else { + sg = (struct scatterlist *)data; + for (i=0; i<use_sg && transferred<len; i++) { + result = sddr09_raw_bulk(us, direction, + sg[i].address, + len-transferred > sg[i].length ? + sg[i].length : len-transferred); + if (result!=US_BULK_TRANSFER_GOOD) + break; + transferred += sg[i].length; + } + } + + return result; +} + +int sddr09_read_data(struct us_data *us, + unsigned long address, + unsigned short sectors, + unsigned char *content, + int use_sg) { + + int result; + unsigned char command[12] = { + 0xe8, 0x20, MSB_of(address>>16), + LSB_of(address>>16), MSB_of(address&0xFFFF), + LSB_of(address&0xFFFF), 0, 0, 0, 0, + MSB_of(sectors), LSB_of(sectors) + }; + + 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, + NULL, 0, SCSI_DATA_READ, content, + sectors*512, use_sg); + + return result; +} + +int sddr09_read_control(struct us_data *us, + unsigned long address, + unsigned short sectors, + unsigned char *content, + int use_sg) { + + 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(sectors), LSB_of(sectors) + }; + + 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, + NULL, 0, SCSI_DATA_READ, content, + sectors*64, use_sg); + + 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, + NULL, 0, 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 + }; + unsigned char content[2]; + + 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, + NULL, 0, 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; +} + +/* +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; +} +*/ + +/* + * Transport for the Sandisk SDDR-09 + */ +int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us) +{ + int result; + unsigned char send_scsi_command[8] = { + 0x41, 0, 0, 0, 0, 0, 0, 0 + }; + 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 deviceID; + unsigned char manufacturerID; + unsigned char *ptr; + +/* + if (us->flags & US_FL_NEED_INIT) { + US_DEBUGP("SDDR-09: initializing\n"); + init_sddr09(us); + us->flags &= ~US_FL_NEED_INIT; + } +*/ + + 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(srb->request_buffer, inquiry_response, 36); + return USB_STOR_TRANSPORT_GOOD; + } + + if (srb->cmnd[0] == READ_CAPACITY) { + + 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 result; + + US_DEBUGP("Device ID = %02X\n", deviceID); + US_DEBUGP("Manuf ID = %02X\n", manufacturerID); + + ptr[0] = 0; + ptr[1] = 0; + ptr[2] = 0; + ptr[3] = 0; + + switch (deviceID) { + + case 0x6e: // 1MB + case 0xe8: + case 0xec: + ptr[4] = 0; + ptr[5] = 0x10; + break; + + case 0xea: // 2MB + case 0x64: + case 0x5d: + ptr[4] = 0; + ptr[5] = 0x20; + break; + + case 0xe3: // 4MB + case 0xe5: + case 0x6b: + case 0xd5: + ptr[4] = 0; + ptr[5] = 0x40; + break; + + case 0xe6: // 8MB + case 0xd6: + ptr[4] = 0; + ptr[5] = 0x80; + break; + + case 0x75: // 32MB + ptr[4] = 0x02; + ptr[5] = 0; + break; + + default: // unknown + ptr[4] = 0; + ptr[5] = 0; + + } + + ptr[6] = 0; + ptr[7] = 0; + + 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 = 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, + NULL, 0, srb->sc_data_direction, + srb->request_buffer, + srb->request_bufflen, srb->use_sg); + + return result; + + } + + return USB_STOR_TRANSPORT_GOOD; +} + diff --git a/drivers/usb/storage/sddr09.h b/drivers/usb/storage/sddr09.h new file mode 100644 index 000000000..76a749528 --- /dev/null +++ b/drivers/usb/storage/sddr09.h @@ -0,0 +1,31 @@ +/* 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); + +#endif diff --git a/drivers/usb/storage/scm.c b/drivers/usb/storage/shuttle_usbat.c index 7bae5e623..f68595c47 100644 --- a/drivers/usb/storage/scm.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -1,7 +1,5 @@ /* 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. @@ -52,7 +50,7 @@ #include "protocol.h" #include "usb.h" #include "debug.h" -#include "scm.h" +#include "shuttle_usbat.h" #include <linux/sched.h> #include <linux/errno.h> @@ -64,6 +62,10 @@ extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe, 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. * @@ -83,62 +85,53 @@ extern int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe, * */ -static int scm_send_control(struct us_data *us, - unsigned char command[8], - unsigned char *xfer_data, - unsigned int xfer_len) { +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; - 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); + 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"); @@ -154,7 +147,7 @@ static int scm_send_control(struct us_data *us, return USB_STOR_TRANSPORT_GOOD; } -static int scm_raw_bulk(struct us_data *us, +static int usbat_raw_bulk(struct us_data *us, int direction, unsigned char *data, unsigned short len) { @@ -182,20 +175,20 @@ static int scm_raw_bulk(struct us_data *us, /* NAK - that means we've retried a few times already */ if (result == -ETIMEDOUT) { - US_DEBUGP("scm_raw_bulk():" + US_DEBUGP("usbat_raw_bulk():" " device NAKed\n"); return US_BULK_TRANSFER_FAILED; } /* -ENOENT -- we canceled this transfer */ if (result == -ENOENT) { - US_DEBUGP("scm_raw_bulk():" + US_DEBUGP("usbat_raw_bulk():" " transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; } if (result == -EPIPE) { - US_DEBUGP("scm_raw_bulk():" + US_DEBUGP("usbat_raw_bulk():" " output pipe stalled\n"); return USB_STOR_TRANSPORT_FAILED; } @@ -220,7 +213,7 @@ static int scm_raw_bulk(struct us_data *us, * Note: direction must be set if command_len == 0. */ -static int scm_bulk_transport(struct us_data *us, +static int usbat_bulk_transport(struct us_data *us, unsigned char *command, unsigned short command_len, int direction, @@ -236,15 +229,19 @@ static int scm_bulk_transport(struct us_data *us, int i; struct scatterlist *sg; char string[64]; + int pipe; +/* if (command_len != 0) { - /* Fix up the command's data length */ + // Fix up the command's data length command[6] = len&0xFF; command[7] = (len>>8)&0xFF; - result = scm_send_control(us, + + + result = usbat_send_control(us, execute, command, command_len); @@ -252,7 +249,7 @@ static int scm_bulk_transport(struct us_data *us, if (result != USB_STOR_TRANSPORT_GOOD) return result; } - +*/ if (len==0) return USB_STOR_TRANSPORT_GOOD; @@ -289,11 +286,11 @@ static int scm_bulk_transport(struct us_data *us, len, use_sg); if (!use_sg) - result = scm_raw_bulk(us, direction, data, len); + result = usbat_raw_bulk(us, direction, data, len); else { sg = (struct scatterlist *)data; for (i=0; i<use_sg && transferred<len; i++) { - result = scm_raw_bulk(us, direction, + result = usbat_raw_bulk(us, direction, sg[i].address, len-transferred > sg[i].length ? sg[i].length : len-transferred); @@ -306,7 +303,7 @@ static int scm_bulk_transport(struct us_data *us, return result; } -int scm_read(struct us_data *us, +int usbat_read(struct us_data *us, unsigned char access, unsigned char reg, unsigned char *content) { @@ -316,17 +313,21 @@ int scm_read(struct us_data *us, 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); + 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 scm_write(struct us_data *us, +int usbat_write(struct us_data *us, unsigned char access, unsigned char reg, unsigned char content) { @@ -336,17 +337,21 @@ int scm_write(struct us_data *us, 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); + 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 scm_set_shuttle_features(struct us_data *us, +int usbat_set_shuttle_features(struct us_data *us, unsigned char external_trigger, unsigned char epp_control, unsigned char mask_byte, @@ -360,15 +365,21 @@ int scm_set_shuttle_features(struct us_data *us, 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; + 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 scm_read_block(struct us_data *us, +int usbat_read_block(struct us_data *us, unsigned char access, unsigned char reg, unsigned char *content, @@ -377,16 +388,27 @@ int scm_read_block(struct us_data *us, int result; unsigned char command[8] = { - 0xC0, access|0x02, reg, 0x00, 0x00, 0x00, 0x00, 0x00 + 0xC0, access|0x02, reg, 0x00, 0x00, 0x00, + LSB_of(len), MSB_of(len) }; - result = scm_bulk_transport(us, - command, 8, 0, content, len, use_sg); + 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; - // US_DEBUGP("SCM: Read data, result %d\n", 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; } @@ -396,7 +418,7 @@ int scm_read_block(struct us_data *us, * an error condition. */ -int scm_wait_not_busy(struct us_data *us) { +int usbat_wait_not_busy(struct us_data *us) { int i; int result; @@ -406,7 +428,7 @@ int scm_wait_not_busy(struct us_data *us) { but probably not more than 15 minutes or so */ for (i=0; i<500; i++) { - result = scm_read(us, SCM_ATA, 0x17, &status); + 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; @@ -432,7 +454,7 @@ int scm_wait_not_busy(struct us_data *us) { return USB_STOR_TRANSPORT_GOOD; } -int scm_write_block(struct us_data *us, +int usbat_write_block(struct us_data *us, unsigned char access, unsigned char reg, unsigned char *content, @@ -441,19 +463,35 @@ int scm_write_block(struct us_data *us, int result; unsigned char command[8] = { - 0x40, access|0x03, reg, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x40, access|0x03, reg, 0x00, 0x00, 0x00, + LSB_of(len), MSB_of(len) }; - result = scm_bulk_transport(us, - command, 8, 0, content, len, use_sg); + result = usbat_send_control(us, + usb_sndctrlpipe(us->pusb_dev,0), + 0x80, + 0x40, + 0, + 0, + command, + 8); - if (result!=USB_STOR_TRANSPORT_GOOD) + 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; - return scm_wait_not_busy(us); + // result = usbat_bulk_transport(us, + // command, 8, 0, content, len, use_sg); + + return usbat_wait_not_busy(us); } -int scm_write_block_test(struct us_data *us, +int usbat_write_block_test(struct us_data *us, unsigned char access, unsigned char *registers, unsigned char *data_out, @@ -467,10 +505,15 @@ int scm_write_block_test(struct us_data *us, 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, 0x00, 0x00, + 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, 0x00, 0x00 + qualifier, timeout, LSB_of(len), MSB_of(len) }; int i; unsigned char data[num_registers*2]; @@ -478,28 +521,44 @@ int scm_write_block_test(struct us_data *us, struct scatterlist *sg; char string[64]; - command[14] = len&0xFF; - command[15] = (len>>8)&0xFF; - for (i=0; i<num_registers; i++) { data[i<<1] = registers[i]; data[1+(i<<1)] = data_out[i]; } - result = scm_bulk_transport(us, - command, 16, 0, data, num_registers*2, 0); + result = usbat_send_control(us, + usb_sndctrlpipe(us->pusb_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; + // 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 */ + // Debug-print the first 48 bytes of the transfer string[0] = 0; for (i=0; i<len && i<48; i++) { @@ -513,13 +572,13 @@ int scm_write_block_test(struct us_data *us, if (string[0]!=0) US_DEBUGP("%s\n", string); - result = scm_raw_bulk(us, SCSI_DATA_WRITE, content, len); + result = usbat_raw_bulk(us, SCSI_DATA_WRITE, content, len); } else { sg = (struct scatterlist *)content; for (i=0; i<use_sg && transferred<len; i++) { - result = scm_raw_bulk(us, SCSI_DATA_WRITE, + result = usbat_raw_bulk(us, SCSI_DATA_WRITE, sg[i].address, len-transferred > sg[i].length ? sg[i].length : len-transferred); @@ -528,14 +587,14 @@ int scm_write_block_test(struct us_data *us, transferred += sg[i].length; } } - +*/ if (result!=USB_STOR_TRANSPORT_GOOD) return result; - return scm_wait_not_busy(us); + return usbat_wait_not_busy(us); } -int scm_multiple_write(struct us_data *us, +int usbat_multiple_write(struct us_data *us, unsigned char access, unsigned char *registers, unsigned char *data_out, @@ -544,8 +603,9 @@ int scm_multiple_write(struct us_data *us, int result; unsigned char data[num_registers*2]; int i; - unsigned char cmd[8] = { - 0x40, access|0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + unsigned char command[8] = { + 0x40, access|0x07, 0x00, 0x00, 0x00, 0x00, + LSB_of(num_registers*2), MSB_of(num_registers*2) }; for (i=0; i<num_registers; i++) { @@ -553,12 +613,73 @@ int scm_multiple_write(struct us_data *us, data[1+(i<<1)] = data_out[i]; } - result = scm_bulk_transport(us, cmd, 8, 0, data, num_registers*2, 0); + 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, 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 scm_wait_not_busy(us); + 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) { @@ -571,39 +692,39 @@ static int hp_8200e_select_and_test_registers(struct us_data *us) { for (selector = 0xA0; selector <= 0xB0; selector += 0x10) { - if ( (result = scm_write(us, SCM_ATA, 0x16, selector)) != + if ( (result = usbat_write(us, USBAT_ATA, 0x16, selector)) != USB_STOR_TRANSPORT_GOOD) return result; - if ( (result = scm_read(us, SCM_ATA, 0x17, &status)) != + if ( (result = usbat_read(us, USBAT_ATA, 0x17, &status)) != USB_STOR_TRANSPORT_GOOD) return result; - if ( (result = scm_read(us, SCM_ATA, 0x16, &status)) != + if ( (result = usbat_read(us, USBAT_ATA, 0x16, &status)) != USB_STOR_TRANSPORT_GOOD) return result; - if ( (result = scm_read(us, SCM_ATA, 0x14, &status)) != + if ( (result = usbat_read(us, USBAT_ATA, 0x14, &status)) != USB_STOR_TRANSPORT_GOOD) return result; - if ( (result = scm_read(us, SCM_ATA, 0x15, &status)) != + if ( (result = usbat_read(us, USBAT_ATA, 0x15, &status)) != USB_STOR_TRANSPORT_GOOD) return result; - if ( (result = scm_write(us, SCM_ATA, 0x14, 0x55)) != + if ( (result = usbat_write(us, USBAT_ATA, 0x14, 0x55)) != USB_STOR_TRANSPORT_GOOD) return result; - if ( (result = scm_write(us, SCM_ATA, 0x15, 0xAA)) != + if ( (result = usbat_write(us, USBAT_ATA, 0x15, 0xAA)) != USB_STOR_TRANSPORT_GOOD) return result; - if ( (result = scm_read(us, SCM_ATA, 0x14, &status)) != + if ( (result = usbat_read(us, USBAT_ATA, 0x14, &status)) != USB_STOR_TRANSPORT_GOOD) return result; - if ( (result = scm_read(us, SCM_ATA, 0x15, &status)) != + if ( (result = usbat_read(us, USBAT_ATA, 0x15, &status)) != USB_STOR_TRANSPORT_GOOD) return result; } @@ -611,89 +732,6 @@ static int hp_8200e_select_and_test_registers(struct us_data *us) { return result; } -int scm_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 = scm_send_control(us, command, data_flags, 1); - - if (result != USB_STOR_TRANSPORT_GOOD) - return result; - - // US_DEBUGP("SCM: User I/O flags -> %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; @@ -701,89 +739,119 @@ static int init_8200e(struct us_data *us) { // 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) + 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 = scm_read_user_io(us, &status)) != + if ( (result = usbat_read_user_io(us, &status)) != USB_STOR_TRANSPORT_GOOD) return result; - if ( (result = scm_read_user_io(us, &status)) != + 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 = scm_write_user_io(us, - SCM_UIO_DRVRST | SCM_UIO_OE1 | SCM_UIO_OE0, - SCM_UIO_EPAD | SCM_UIO_1)) != USB_STOR_TRANSPORT_GOOD) + 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 = scm_write_user_io(us, - SCM_UIO_OE1 | SCM_UIO_OE0, - SCM_UIO_EPAD | SCM_UIO_1)) != USB_STOR_TRANSPORT_GOOD) + 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 = scm_write(us, SCM_ISA, 0x3F, 0x80)) != + 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 = scm_read(us, SCM_ISA, 0x27, &status)) != + if ( (result = usbat_read(us, USBAT_ISA, 0x27, &status)) != USB_STOR_TRANSPORT_GOOD) return result; - if ( (result = scm_read_user_io(us, &status)) != + 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; - if ( (result = scm_read_user_io(us, &status)) != + 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 = scm_write_user_io(us, - SCM_UIO_ACKD |SCM_UIO_OE1 | SCM_UIO_OE0, - SCM_UIO_EPAD | SCM_UIO_1)) != USB_STOR_TRANSPORT_GOOD) + 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; - if ( (result = scm_read_user_io(us, &status)) != + 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 = scm_read_user_io(us, &status)) != + 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; - if ( (result = scm_set_shuttle_features(us, + 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; } @@ -923,7 +991,7 @@ int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us) data[i] = (i-7 >= srb->cmd_len) ? 0 : srb->cmnd[i-7]; } - result = scm_write_block_test(us, SCM_ATA, + result = usbat_write_block_test(us, USBAT_ATA, registers, data, 19, 0x10, 0x17, 0xFD, 0x30, srb->request_buffer, @@ -932,16 +1000,16 @@ int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us) return result; } - if ( (result = scm_multiple_write(us, - SCM_ATA, + 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 = scm_write_block(us, - SCM_ATA, 0x10, srb->cmnd, 12, 0)) != + if ( (result = usbat_write_block(us, + USBAT_ATA, 0x10, srb->cmnd, 12, 0)) != USB_STOR_TRANSPORT_GOOD) { return result; } @@ -953,14 +1021,15 @@ int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us) // How many bytes to read in? Check cylL register - if ( (result = scm_read(us, SCM_ATA, 0x14, &status)) != + 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 = scm_read(us, SCM_ATA, 0x15, &status)) != + if ( (result = usbat_read(us, USBAT_ATA, 0x15, + &status)) != USB_STOR_TRANSPORT_GOOD) { return result; } @@ -970,7 +1039,7 @@ int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us) len = status; - result = scm_read_block(us, SCM_ATA, 0x10, + result = usbat_read_block(us, USBAT_ATA, 0x10, srb->request_buffer, len, srb->use_sg); /* Debug-print the first 32 bytes of the transfer */ @@ -996,161 +1065,3 @@ int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us) } -/* - * 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 --git a/drivers/usb/storage/scm.h b/drivers/usb/storage/shuttle_usbat.h index f57463a1e..eede2651f 100644 --- a/drivers/usb/storage/scm.h +++ b/drivers/usb/storage/shuttle_usbat.h @@ -1,8 +1,6 @@ /* 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) * @@ -23,60 +21,56 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef _USB_SCM_H -#define _USB_SCM_H +#ifndef _USB_SHUTTLE_USBAT_H +#define _USB_SHUTTLE_USBAT_H -#define SCM_EPP_PORT 0x10 -#define SCM_EPP_REGISTER 0x30 -#define SCM_ATA 0x40 -#define SCM_ISA 0x50 +#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 SCM_UIO_EPAD 0x80 // Enable Peripheral Control Signals -#define SCM_UIO_CDT 0x40 // Card Detect (Read Only) +#define USBAT_UIO_EPAD 0x80 // Enable Peripheral Control Signals +#define USBAT_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) +#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 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 +#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 SCM_UIO_OE0 0x10 // I/O 0 set=output/clr=input -#define SCM_UIO_ADPRST 0x01 // Reset SCM chip +#define USBAT_UIO_OE0 0x10 // I/O 0 set=output/clr=input +#define USBAT_UIO_ADPRST 0x01 // Reset SCM chip -/* SCM-specific commands */ +/* USBAT-specific commands */ -extern int scm_read(struct us_data *us, unsigned char access, +extern int usbat_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, +extern int usbat_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, +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 scm_write_block(struct us_data *us, unsigned char access, +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 scm_multiple_write(struct us_data *us, unsigned char access, +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 scm_read_user_io(struct us_data *us, unsigned char *data_flags); -extern int scm_write_user_io(struct us_data *us, +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); -/* Sandisk SDDR-09 stuff */ - -extern int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us); - #endif diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 88c847641..69dfcfde8 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -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.4 2000/07/25 23:04:47 mdharm Exp $ * * Current development and maintainance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -203,7 +203,7 @@ static int us_transfer_partial(struct us_data *us, char *buf, int length) 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 @@ static int us_transfer_partial(struct us_data *us, char *buf, int length) * 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 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us) 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 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us) 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 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us) 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 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us) /* 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 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us) /* 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 */ @@ -718,7 +728,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) /* 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 +765,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) 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); diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h index 55e12f79f..9d0993c1e 100644 --- a/drivers/usb/storage/transport.h +++ b/drivers/usb/storage/transport.h @@ -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 @@ extern unsigned char us_direction[256/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 --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 99986371f..c82d7e914 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -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.14 2000/07/27 14:42:43 groovyjava 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 <linux/module.h> @@ -117,9 +120,9 @@ static int usb_stor_control_thread(void * __us) /* 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 @@ static int usb_stor_control_thread(void * __us) 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 @@ static int usb_stor_control_thread(void * __us) 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 @@ static int usb_stor_control_thread(void * __us) 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 @@ static struct us_unusual_dev us_unusual_dev_list[] = { 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 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum) /* 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 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum) #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; @@ -855,3 +874,6 @@ void __exit usb_stor_exit(void) module_init(usb_stor_init) ; module_exit(usb_stor_exit) ; + +MODULE_AUTHOR("Michael Gee <michael@linuxspecific.com>, David L. Brown, Jr. <usb-storage@davidb.org>, Matthew Dharm <mdharm-usb@one-eyed-alien.net>"); +MODULE_DESCRIPTION("USB Mass Storage driver"); diff --git a/drivers/usb/uhci.c b/drivers/usb/uhci.c index 31be1c0e2..8423b448a 100644 --- a/drivers/usb/uhci.c +++ b/drivers/usb/uhci.c @@ -49,6 +49,7 @@ static int handle_pm_event(struct pm_dev *dev, pm_request_t rqst, void *data); 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 @@ void cleanup_module(void) 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 --git a/drivers/usb/usb-ohci.c b/drivers/usb/usb-ohci.c index 48a5df48e..cfa871503 100644 --- a/drivers/usb/usb-ohci.c +++ b/drivers/usb/usb-ohci.c @@ -65,6 +65,9 @@ */ #include <linux/adb.h> #include <linux/pmu.h> +#ifndef CONFIG_PM +#define CONFIG_PM +#endif #endif @@ -415,9 +418,11 @@ static int sohci_submit_urb (urb_t * urb) 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 @@ static int sohci_submit_urb (urb_t * urb) /* 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))) { @@ -1730,7 +1737,9 @@ static int rh_submit_urb (urb_t * urb) 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 +1889,9 @@ static void hc_interrupt (int irq, void * __ohci, struct pt_regs * r) 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 +1921,8 @@ static void hc_interrupt (int irq, void * __ohci, struct pt_regs * r) } writel (ints, ®s->intrstatus); writel (OHCI_INTR_MIE, ®s->intrenable); + + /* FIXME: check URB timeouts */ } /*-------------------------------------------------------------------------*/ @@ -1921,7 +1934,7 @@ static ohci_t * __devinit hc_alloc_ohci (void * mem_base) 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 +1945,7 @@ static ohci_t * __devinit hc_alloc_ohci (void * mem_base) bus = usb_alloc_bus (&sohci_device_operations); if (!bus) { - free_pages ((unsigned long) ohci, 1); + kfree (ohci); return NULL; } @@ -1974,7 +1987,7 @@ static void hc_release_ohci (ohci_t * ohci) /* unmap the IO address space */ iounmap (ohci->regs); - free_pages ((unsigned long) ohci, 1); + kfree (ohci); } /*-------------------------------------------------------------------------*/ @@ -2085,13 +2098,27 @@ static void hc_restart (ohci_t *ohci) 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 +2130,6 @@ ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) } } - /* 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 +2163,8 @@ ohci_pci_remove (struct pci_dev *dev) &ohci->regs->control); hc_release_ohci (ohci); + + release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0)); } @@ -2233,7 +2253,7 @@ ohci_pci_resume (struct pci_dev *dev) /*-------------------------------------------------------------------------*/ -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 +2348,5 @@ module_exit (ohci_hcd_cleanup); #endif /* MODULE */ +MODULE_AUTHOR ("Roman Weissgaerber <weissg@vienna.at>"); MODULE_DESCRIPTION ("USB OHCI Host Controller Driver"); diff --git a/drivers/usb/usb-uhci.c b/drivers/usb/usb-uhci.c index 626bfc93c..e82fa78a0 100644 --- a/drivers/usb/usb-uhci.c +++ b/drivers/usb/usb-uhci.c @@ -2885,4 +2885,6 @@ void cleanup_module (void) uhci_cleanup (); } +MODULE_AUTHOR("Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber"); +MODULE_DESCRIPTION("USB Universal Host Controller Interface driver"); #endif //MODULE diff --git a/drivers/usb/usbkbd.c b/drivers/usb/usbkbd.c index 42f82604e..89cc76537 100644 --- a/drivers/usb/usbkbd.c +++ b/drivers/usb/usbkbd.c @@ -36,6 +36,7 @@ #include <linux/usb.h> MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); +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 --git a/drivers/usb/usbmouse.c b/drivers/usb/usbmouse.c index 55bd14fdb..39df8e5e0 100644 --- a/drivers/usb/usbmouse.c +++ b/drivers/usb/usbmouse.c @@ -36,6 +36,7 @@ #include <linux/usb.h> MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); +MODULE_DESCRIPTION("USB HID Boot Protocol mouse driver"); struct usb_mouse { signed char data[8]; diff --git a/drivers/usb/wacom.c b/drivers/usb/wacom.c index de2821e47..b74a003e8 100644 --- a/drivers/usb/wacom.c +++ b/drivers/usb/wacom.c @@ -51,6 +51,7 @@ #include <linux/usb.h> MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); +MODULE_DESCRIPTION("USB Wacom Graphire and Wacom Intuos tablet driver"); /* * Wacom Graphire packet: diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c index 4b388f60b..f206bef56 100644 --- a/drivers/video/riva/fbdev.c +++ b/drivers/video/riva/fbdev.c @@ -857,7 +857,7 @@ static int rivafb_set_var (struct fb_var_screeninfo *var, int con, v.blue.offset = 0; #endif v.red.length = 5; - v.green.length = 5; + v.green.length = 6; v.blue.length = 5; break; #endif @@ -1390,8 +1390,8 @@ static int riva_setcolreg (unsigned regno, unsigned red, unsigned green, ((green & 0xf800) << 2) | ((blue & 0xf800) >> 3); #else rivainfo->con_cmap.cfb16[regno] = - ((red & 0xf800) >> 1) | - ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11); + ((red & 0xf800) >> 0) | + ((green & 0xf800) >> 5) | ((blue & 0xf800) >> 11); #endif break; #endif /* FBCON_HAS_CFB16 */ diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 4fb5b1685..422531158 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -512,7 +512,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) retval = PTR_ERR(interpreter); if (IS_ERR(interpreter)) goto out_free_interp; - retval = kernel_read(interpreter, 0, bprm->buf, 128); + retval = kernel_read(interpreter, 0, bprm->buf, BINPRM_BUF_SIZE); if (retval < 0) goto out_free_dentry; diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index f9c30df1b..c16536479 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -182,7 +182,7 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) { struct binfmt_entry *fmt; struct file * file; - char iname[128]; + char iname[BINPRM_BUF_SIZE]; char *iname_addr = iname; int retval; @@ -194,8 +194,8 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) read_lock(&entries_lock); fmt = check_file(bprm); if (fmt) { - strncpy(iname, fmt->interpreter, 127); - iname[127] = '\0'; + strncpy(iname, fmt->interpreter, BINPRM_BUF_SIZE - 1); + iname[BINPRM_BUF_SIZE - 1] = '\0'; } read_unlock(&entries_lock); if (!fmt) @@ -324,7 +324,7 @@ static int proc_write_register(struct file *file, const char *buffer, /* more sanity checks */ if (err || !(!cnt || (!(--cnt) && (*sp == '\n'))) || - (e->size < 1) || ((e->size + e->offset) > 127) || + (e->size < 1) || ((e->size + e->offset) > (BINPRM_BUF_SIZE - 1)) || !(e->proc_name) || !(e->interpreter) || entry_proc_setup(e)) goto free_err; diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c index 3d5023e2d..ae7de4c24 100644 --- a/fs/binfmt_script.c +++ b/fs/binfmt_script.c @@ -18,7 +18,7 @@ static int load_script(struct linux_binprm *bprm,struct pt_regs *regs) { char *cp, *i_name, *i_arg; struct file *file; - char interp[128]; + char interp[BINPRM_BUF_SIZE]; int retval; if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!') || (bprm->sh_bang)) @@ -33,9 +33,9 @@ static int load_script(struct linux_binprm *bprm,struct pt_regs *regs) fput(bprm->file); bprm->file = NULL; - bprm->buf[127] = '\0'; + bprm->buf[BINPRM_BUF_SIZE - 1] = '\0'; if ((cp = strchr(bprm->buf, '\n')) == NULL) - cp = bprm->buf+127; + cp = bprm->buf+BINPRM_BUF_SIZE-1; *cp = '\0'; while (cp > bprm->buf) { cp--; diff --git a/fs/buffer.c b/fs/buffer.c index dad4fbcfb..341dfe591 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1341,13 +1341,27 @@ static void create_empty_buffers(struct page *page, struct inode *inode, unsigne page_cache_get(page); } +/* + * We are taking a block for data and we don't want any output from any + * buffer-cache aliases starting from return from that function and + * until the moment when something will explicitly mark the buffer + * dirty (hopefully that will not happen until we will free that block ;-) + * We don't even need to mark it not-uptodate - nobody can expect + * anything from a newly allocated buffer anyway. We used to used + * unmap_buffer() for such invalidation, but that was wrong. We definitely + * don't want to mark the alias unmapped, for example - it would confuse + * anyone who might pick it with bread() afterwards... + */ + static void unmap_underlying_metadata(struct buffer_head * bh) { struct buffer_head *old_bh; old_bh = get_hash_table(bh->b_dev, bh->b_blocknr, bh->b_size); if (old_bh) { - unmap_buffer(old_bh); + mark_buffer_clean(old_bh); + wait_on_buffer(old_bh); + clear_bit(BH_Req, &old_bh->b_state); /* Here we could run brelse or bforget. We use bforget because it will try to put the buffer in the freelist. */ diff --git a/fs/dcache.c b/fs/dcache.c index 729b48855..9be3e8cdc 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -14,6 +14,7 @@ * the dcache entry is deleted or garbage collected. */ +#include <linux/config.h> #include <linux/string.h> #include <linux/mm.h> #include <linux/fs.h> diff --git a/fs/devices.c b/fs/devices.c index dd7db7730..85fb7e519 100644 --- a/fs/devices.c +++ b/fs/devices.c @@ -88,11 +88,11 @@ static struct file_operations * get_chrfops(unsigned int major, unsigned int min char name[20]; sprintf(name, "char-major-%d", major); request_module(name); - } - read_lock(&chrdevs_lock); - ret = fops_get(chrdevs[major].fops); - read_unlock(&chrdevs_lock); + read_lock(&chrdevs_lock); + ret = fops_get(chrdevs[major].fops); + read_unlock(&chrdevs_lock); + } #endif return ret; } @@ -555,7 +555,7 @@ static inline int must_not_trace_exec(struct task_struct * p) /* * Fill the binprm structure from the inode. - * Check permissions, then read the first 512 bytes + * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes */ int prepare_binprm(struct linux_binprm *bprm) { @@ -646,8 +646,8 @@ int prepare_binprm(struct linux_binprm *bprm) } } - memset(bprm->buf,0,sizeof(bprm->buf)); - return kernel_read(bprm->file,0,bprm->buf,128); + memset(bprm->buf,0,BINPRM_BUF_SIZE); + return kernel_read(bprm->file,0,bprm->buf,BINPRM_BUF_SIZE); } /* @@ -819,15 +819,15 @@ int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs int retval; int i; - bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); - memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0])); - file = open_exec(filename); retval = PTR_ERR(file); if (IS_ERR(file)) return retval; + bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); + memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0])); + bprm.file = file; bprm.filename = filename; bprm.sh_bang = 0; diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c index a3f8ae4ce..8ca28e0a0 100644 --- a/fs/ext2/balloc.c +++ b/fs/ext2/balloc.c @@ -16,7 +16,6 @@ #include <linux/locks.h> #include <linux/quotaops.h> - /* * balloc.c contains the blocks allocation and deallocation routines */ @@ -379,10 +378,8 @@ int ext2_new_block (const struct inode * inode, unsigned long goal, ((sb->u.ext2_sb.s_resuid != current->fsuid) && (sb->u.ext2_sb.s_resgid == 0 || !in_group_p (sb->u.ext2_sb.s_resgid)) && - !capable(CAP_SYS_RESOURCE))) { - unlock_super (sb); - return 0; - } + !capable(CAP_SYS_RESOURCE))) + goto out; ext2_debug ("goal=%lu.\n", goal); @@ -475,16 +472,13 @@ repeat: gdp = ext2_get_group_desc (sb, i, &bh2); if (!gdp) { *err = -EIO; - unlock_super (sb); - return 0; + goto out; } if (le16_to_cpu(gdp->bg_free_blocks_count) > 0) break; } - if (k >= sb->u.ext2_sb.s_groups_count) { - unlock_super (sb); - return 0; - } + if (k >= sb->u.ext2_sb.s_groups_count) + goto out; bitmap_nr = load_block_bitmap (sb, i); if (bitmap_nr < 0) goto io_error; @@ -500,8 +494,7 @@ repeat: if (j >= EXT2_BLOCKS_PER_GROUP(sb)) { ext2_error (sb, "ext2_new_block", "Free blocks count corrupted for block group %d", i); - unlock_super (sb); - return 0; + goto out; } search_back: @@ -520,9 +513,8 @@ got_block: * Check quota for allocation of this block. */ if(DQUOT_ALLOC_BLOCK(sb, inode, 1)) { - unlock_super(sb); *err = -EDQUOT; - return 0; + goto out; } tmp = j + i * EXT2_BLOCKS_PER_GROUP(sb) + le32_to_cpu(es->s_first_data_block); @@ -550,31 +542,50 @@ got_block: #ifdef EXT2_PREALLOCATE if (prealloc_block) { int prealloc_goal; + unsigned long next_block = tmp + 1; prealloc_goal = es->s_prealloc_blocks ? es->s_prealloc_blocks : EXT2_DEFAULT_PREALLOC_BLOCKS; + /* Writer: ->i_prealloc* */ + /* + * Can't happen right now, will need handling if we go for + * per-group spinlocks. Handling == skipping preallocation if + * condition below will be true. For now there is no legitimate + * way it could happen, thus the BUG(). + */ + if (*prealloc_count) + BUG(); *prealloc_count = 0; - *prealloc_block = tmp + 1; + *prealloc_block = next_block; + /* Writer: end */ for (k = 1; k < prealloc_goal && (j + k) < EXT2_BLOCKS_PER_GROUP(sb); - k++) { + k++, next_block++) { if (DQUOT_PREALLOC_BLOCK(sb, inode, 1)) break; - if (ext2_set_bit (j + k, bh->b_data)) { + /* Writer: ->i_prealloc* */ + if (*prealloc_block + *prealloc_count != next_block || + ext2_set_bit (j + k, bh->b_data)) { + /* Writer: end */ DQUOT_FREE_BLOCK(sb, inode, 1); break; } (*prealloc_count)++; + /* Writer: end */ } + /* + * As soon as we go for per-group spinlocks we'll need these + * done inside the loop above. + */ gdp->bg_free_blocks_count = cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) - - *prealloc_count); + (k - 1)); es->s_free_blocks_count = cpu_to_le32(le32_to_cpu(es->s_free_blocks_count) - - *prealloc_count); + (k - 1)); ext2_debug ("Preallocated a further %lu bits.\n", - *prealloc_count); + (k - 1)); } #endif @@ -591,8 +602,7 @@ got_block: "block(%d) >= blocks count(%d) - " "block_group = %d, es == %p ",j, le32_to_cpu(es->s_blocks_count), i, es); - unlock_super (sb); - return 0; + goto out; } ext2_debug ("allocating block %d. " @@ -609,6 +619,7 @@ got_block: io_error: *err = -EIO; +out: unlock_super (sb); return 0; diff --git a/fs/ext2/file.c b/fs/ext2/file.c index 1b9983e24..27b1fcbcb 100644 --- a/fs/ext2/file.c +++ b/fs/ext2/file.c @@ -20,7 +20,6 @@ #include <linux/fs.h> #include <linux/sched.h> -#include <linux/smp_lock.h> static loff_t ext2_file_lseek(struct file *, loff_t, int); static int ext2_open_file (struct inode *, struct file *); @@ -74,11 +73,8 @@ static loff_t ext2_file_lseek( */ static int ext2_release_file (struct inode * inode, struct file * filp) { - if (filp->f_mode & FMODE_WRITE) { - lock_kernel(); + if (filp->f_mode & FMODE_WRITE) ext2_discard_prealloc (inode); - unlock_kernel(); - } return 0; } diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 4580c87e0..c7234e7b5 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -35,9 +35,7 @@ static int ext2_update_inode(struct inode * inode, int do_sync); */ void ext2_put_inode (struct inode * inode) { - lock_kernel(); ext2_discard_prealloc (inode); - unlock_kernel(); } /* @@ -66,19 +64,6 @@ no_delete: clear_inode(inode); /* We must guarantee clearing of inode... */ } -#define inode_bmap(inode, nr) (le32_to_cpu((inode)->u.ext2_i.i_data[(nr)])) - -static inline int block_bmap (struct buffer_head * bh, int nr) -{ - int tmp; - - if (!bh) - return 0; - tmp = le32_to_cpu(((u32 *) bh->b_data)[nr]); - brelse (bh); - return tmp; -} - /* * ext2_discard_prealloc and ext2_alloc_block are atomic wrt. the * superblock in the same manner as are ext2_free_blocks and @@ -91,11 +76,13 @@ void ext2_discard_prealloc (struct inode * inode) #ifdef EXT2_PREALLOCATE unsigned short total; + lock_kernel(); if (inode->u.ext2_i.i_prealloc_count) { total = inode->u.ext2_i.i_prealloc_count; inode->u.ext2_i.i_prealloc_count = 0; ext2_free_blocks (inode, inode->u.ext2_i.i_prealloc_block, total); } + unlock_kernel(); #endif } @@ -135,69 +122,181 @@ static int ext2_alloc_block (struct inode * inode, unsigned long goal, int *err) return result; } -static inline long ext2_block_map (struct inode * inode, long block) +typedef struct { + u32 *p; + u32 key; + struct buffer_head *bh; +} Indirect; + +static inline void add_chain(Indirect *p, struct buffer_head *bh, u32 *v) +{ + p->key = *(p->p = v); + p->bh = bh; +} + +static inline int verify_chain(Indirect *from, Indirect *to) +{ + while (from <= to && from->key == *from->p) + from++; + return (from > to); +} + +/** + * ext2_block_to_path - parse the block number into array of offsets + * @inode: inode in question (we are only interested in its superblock) + * @i_block: block number to be parsed + * @offsets: array to store the offsets in + * + * To store the locations of file's data ext2 uses a data structure common + * for UNIX filesystems - tree of pointers anchored in the inode, with + * data blocks at leaves and indirect blocks in intermediate nodes. + * This function translates the block number into path in that tree - + * return value is the path length and @offsets[n] is the offset of + * pointer to (n+1)th node in the nth one. If @block is out of range + * (negative or too large) warning is printed and zero returned. + * + * Note: function doesn't find node addresses, so no IO is needed. All + * we need to know is the capacity of indirect blocks (taken from the + * inode->i_sb). + */ + +/* + * Portability note: the last comparison (check that we fit into triple + * indirect block) is spelled differently, because otherwise on an + * architecture with 32-bit longs and 8Kb pages we might get into trouble + * if our filesystem had 8Kb blocks. We might use long long, but that would + * kill us on x86. Oh, well, at least the sign propagation does not matter - + * i_block would have to be negative in the very beginning, so we would not + * get there at all. + */ + +static int ext2_block_to_path(struct inode *inode, long i_block, int offsets[4]) { - int i, ret; int ptrs = EXT2_ADDR_PER_BLOCK(inode->i_sb); int ptrs_bits = EXT2_ADDR_PER_BLOCK_BITS(inode->i_sb); - - ret = 0; - lock_kernel(); - if (block < 0) { - ext2_warning (inode->i_sb, "ext2_block_map", "block < 0"); - goto out; - } - if (block >= EXT2_NDIR_BLOCKS + ptrs + - (1 << (ptrs_bits * 2)) + - ((1 << (ptrs_bits * 2)) << ptrs_bits)) { - ext2_warning (inode->i_sb, "ext2_block_map", "block > big"); - goto out; - } - if (block < EXT2_NDIR_BLOCKS) { - ret = inode_bmap (inode, block); - goto out; - } - block -= EXT2_NDIR_BLOCKS; - if (block < ptrs) { - i = inode_bmap (inode, EXT2_IND_BLOCK); - if (!i) - goto out; - ret = block_bmap (bread (inode->i_dev, i, - inode->i_sb->s_blocksize), block); - goto out; + const long direct_blocks = EXT2_NDIR_BLOCKS, + indirect_blocks = ptrs, + double_blocks = (1 << (ptrs_bits * 2)); + int n = 0; + + if (i_block < 0) { + ext2_warning (inode->i_sb, "ext2_block_to_path", "block < 0"); + } else if (i_block < direct_blocks) { + offsets[n++] = i_block; + } else if ( (i_block -= direct_blocks) < indirect_blocks) { + offsets[n++] = EXT2_IND_BLOCK; + offsets[n++] = i_block; + } else if ((i_block -= indirect_blocks) < double_blocks) { + offsets[n++] = EXT2_DIND_BLOCK; + offsets[n++] = i_block >> ptrs_bits; + offsets[n++] = i_block & (ptrs - 1); + } else if (((i_block -= double_blocks) >> (ptrs_bits * 2)) < ptrs) { + offsets[n++] = EXT2_TIND_BLOCK; + offsets[n++] = i_block >> (ptrs_bits * 2); + offsets[n++] = (i_block >> ptrs_bits) & (ptrs - 1); + offsets[n++] = i_block & (ptrs - 1); + } else { + ext2_warning (inode->i_sb, "ext2_block_to_path", "block > big"); } - block -= ptrs; - if (block < (1 << (ptrs_bits * 2))) { - i = inode_bmap (inode, EXT2_DIND_BLOCK); - if (!i) - goto out; - i = block_bmap (bread (inode->i_dev, i, - inode->i_sb->s_blocksize), - block >> ptrs_bits); - if (!i) - goto out; - ret = block_bmap (bread (inode->i_dev, i, - inode->i_sb->s_blocksize), - block & (ptrs - 1)); - goto out; + return n; +} + +/** + * ext2_get_branch - read the chain of indirect blocks leading to data + * @inode: inode in question + * @depth: depth of the chain (1 - direct pointer, etc.) + * @offsets: offsets of pointers in inode/indirect blocks + * @chain: place to store the result + * @err: here we store the error value + * + * Function fills the array of triples <key, p, bh> and returns %NULL + * if everything went OK or the pointer to the last filled triple + * (incomplete one) otherwise. Upon the return chain[i].key contains + * the number of (i+1)-th block in the chain (as it is stored in memory, + * i.e. little-endian 32-bit), chain[i].p contains the address of that + * number (it points into struct inode for i==0 and into the bh->b_data + * for i>0) and chain[i].bh points to the buffer_head of i-th indirect + * block for i>0 and NULL for i==0. In other words, it holds the block + * numbers of the chain, addresses they were taken from (and where we can + * verify that chain did not change) and buffer_heads hosting these + * numbers. + * + * Function stops when it stumbles upon zero pointer (absent block) + * (pointer to last triple returned, *@err == 0) + * or when it gets an IO error reading an indirect block + * (ditto, *@err == -EIO) + * or when it notices that chain had been changed while it was reading + * (ditto, *@err == -EAGAIN) + * or when it reads all @depth-1 indirect blocks successfully and finds + * the whole chain, all way to the data (returns %NULL, *err == 0). + */ +static inline Indirect *ext2_get_branch(struct inode *inode, + int depth, + int *offsets, + Indirect chain[4], + int *err) +{ + kdev_t dev = inode->i_dev; + int size = inode->i_sb->s_blocksize; + Indirect *p = chain; + struct buffer_head *bh; + + *err = 0; + /* i_data is not going away, no lock needed */ + add_chain (chain, NULL, inode->u.ext2_i.i_data + *offsets); + if (!p->key) + goto no_block; + /* + * switch below is merely an unrolled loop - body should be + * repeated depth-1 times. Maybe loop would be actually better, + * but that way we get straight execution path in normal cases. + * Easy to change, anyway - all cases in switch are literally + * identical. + */ + switch (depth) { + case 4: + bh = bread(dev, le32_to_cpu(p->key), size); + if (!bh) + goto failure; + /* Reader: pointers */ + if (!verify_chain(chain, p)) + goto changed; + add_chain(++p, bh, (u32*)bh->b_data + *++offsets); + /* Reader: end */ + if (!p->key) + goto no_block; + case 3: + bh = bread(dev, le32_to_cpu(p->key), size); + if (!bh) + goto failure; + /* Reader: pointers */ + if (!verify_chain(chain, p)) + goto changed; + add_chain(++p, bh, (u32*)bh->b_data + *++offsets); + /* Reader: end */ + if (!p->key) + goto no_block; + case 2: + bh = bread(dev, le32_to_cpu(p->key), size); + if (!bh) + goto failure; + /* Reader: pointers */ + if (!verify_chain(chain, p)) + goto changed; + add_chain(++p, bh, (u32*)bh->b_data + *++offsets); + /* Reader: end */ + if (!p->key) + goto no_block; } - block -= (1 << (ptrs_bits * 2)); - i = inode_bmap (inode, EXT2_TIND_BLOCK); - if (!i) - goto out; - i = block_bmap (bread (inode->i_dev, i, inode->i_sb->s_blocksize), - block >> (ptrs_bits * 2)); - if (!i) - goto out; - i = block_bmap (bread (inode->i_dev, i, inode->i_sb->s_blocksize), - (block >> ptrs_bits) & (ptrs - 1)); - if (!i) - goto out; - ret = block_bmap (bread (inode->i_dev, i, inode->i_sb->s_blocksize), - block & (ptrs - 1)); -out: - unlock_kernel(); - return ret; + return NULL; + +changed: + *err = -EAGAIN; + goto no_block; +failure: + *err = -EIO; +no_block: + return p; } static struct buffer_head * inode_getblk (struct inode * inode, int nr, @@ -396,28 +495,37 @@ static int ext2_get_block(struct inode *inode, long iblock, struct buffer_head * { int ret, err, new; struct buffer_head *bh; - unsigned long ptr, phys; - /* - * block pointers per block - */ - unsigned long ptrs = EXT2_ADDR_PER_BLOCK(inode->i_sb); - int ptrs_bits = EXT2_ADDR_PER_BLOCK_BITS(inode->i_sb); - const int direct_blocks = EXT2_NDIR_BLOCKS, - indirect_blocks = ptrs, - double_blocks = (1 << (ptrs_bits * 2)), - triple_blocks = (1 << (ptrs_bits * 3)); + unsigned long phys; + int offsets[4]; + int *p; + Indirect chain[4]; + Indirect *partial; + int depth; + + depth = ext2_block_to_path(inode, iblock, offsets); + if (depth == 0) + goto abort; + + lock_kernel(); + partial = ext2_get_branch(inode, depth, offsets, chain, &err); + + if (!partial) { + unlock_kernel(); + for (partial = chain + depth - 1; partial > chain; partial--) + brelse(partial->bh); + bh_result->b_dev = inode->i_dev; + bh_result->b_blocknr = le32_to_cpu(chain[depth-1].key); + bh_result->b_state |= (1UL << BH_Mapped); + return 0; + } + + while (partial > chain) { + brelse(partial->bh); + partial--; + } if (!create) { - /* - * Will clean this up further, ext2_block_map() should use the - * bh instead of an integer block-number interface. - */ - phys = ext2_block_map(inode, iblock); - if (phys) { - bh_result->b_dev = inode->i_dev; - bh_result->b_blocknr = phys; - bh_result->b_state |= (1UL << BH_Mapped); - } + unlock_kernel(); return 0; } @@ -426,14 +534,6 @@ static int ext2_get_block(struct inode *inode, long iblock, struct buffer_head * ret = 0; bh = NULL; - lock_kernel(); - - if (iblock < 0) - goto abort_negative; - if (iblock > direct_blocks + indirect_blocks + - double_blocks + triple_blocks) - goto abort_too_big; - /* * If this is a sequential block allocation, set the next_alloc_block * to this block now so that all the indblock and data block @@ -450,7 +550,6 @@ static int ext2_get_block(struct inode *inode, long iblock, struct buffer_head * } err = 0; - ptr = iblock; /* * ok, these macros clean the logic up a bit and make @@ -465,27 +564,20 @@ static int ext2_get_block(struct inode *inode, long iblock, struct buffer_head * #define GET_INDIRECT_PTR(x) \ block_getblk (inode, bh, x, iblock, &err, 1, NULL, NULL); - if (ptr < direct_blocks) { - bh = GET_INODE_DATABLOCK(ptr); + p = offsets; + if (depth == 1) { + bh = GET_INODE_DATABLOCK(*p); goto out; } - ptr -= direct_blocks; - if (ptr < indirect_blocks) { - bh = GET_INODE_PTR(EXT2_IND_BLOCK); - goto get_indirect; + bh = GET_INODE_PTR(*p); + switch (depth) { + default: /* case 4: */ + bh = GET_INDIRECT_PTR(*++p); + case 3: + bh = GET_INDIRECT_PTR(*++p); + case 2: + bh = GET_INDIRECT_DATABLOCK(*++p); } - ptr -= indirect_blocks; - if (ptr < double_blocks) { - bh = GET_INODE_PTR(EXT2_DIND_BLOCK); - goto get_double; - } - ptr -= double_blocks; - bh = GET_INODE_PTR(EXT2_TIND_BLOCK); - bh = GET_INDIRECT_PTR(ptr >> (ptrs_bits * 2)); -get_double: - bh = GET_INDIRECT_PTR((ptr >> ptrs_bits) & (ptrs - 1)); -get_indirect: - bh = GET_INDIRECT_DATABLOCK(ptr & (ptrs - 1)); #undef GET_INODE_DATABLOCK #undef GET_INODE_PTR @@ -505,17 +597,9 @@ out: bh_result->b_state |= (1UL << BH_Mapped); /* safe */ if (new) bh_result->b_state |= (1UL << BH_New); -abort: unlock_kernel(); +abort: return err; - -abort_negative: - ext2_warning (inode->i_sb, "ext2_get_block", "block < 0"); - goto abort; - -abort_too_big: - ext2_warning (inode->i_sb, "ext2_get_block", "block > big"); - goto abort; } struct buffer_head * ext2_getblk(struct inode * inode, long block, int create, int * err) diff --git a/fs/ext2/super.c b/fs/ext2/super.c index e395c75a1..bca514ee5 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -254,53 +254,56 @@ static int parse_options (char * options, unsigned long * sb_block, return 1; } -static void ext2_setup_super (struct super_block * sb, - struct ext2_super_block * es) +static int ext2_setup_super (struct super_block * sb, + struct ext2_super_block * es, + int read_only) { + int res = 0; if (le32_to_cpu(es->s_rev_level) > EXT2_MAX_SUPP_REV) { printk ("EXT2-fs warning: revision level too high, " "forcing read/only mode\n"); - sb->s_flags |= MS_RDONLY; + res = MS_RDONLY; } - if (!(sb->s_flags & MS_RDONLY)) { - if (!(sb->u.ext2_sb.s_mount_state & EXT2_VALID_FS)) - printk ("EXT2-fs warning: mounting unchecked fs, " - "running e2fsck is recommended\n"); - else if ((sb->u.ext2_sb.s_mount_state & EXT2_ERROR_FS)) - printk ("EXT2-fs warning: mounting fs with errors, " - "running e2fsck is recommended\n"); - else if ((__s16) le16_to_cpu(es->s_max_mnt_count) >= 0 && - le16_to_cpu(es->s_mnt_count) >= - (unsigned short) (__s16) le16_to_cpu(es->s_max_mnt_count)) - printk ("EXT2-fs warning: maximal mount count reached, " - "running e2fsck is recommended\n"); - else if (le32_to_cpu(es->s_checkinterval) && - (le32_to_cpu(es->s_lastcheck) + le32_to_cpu(es->s_checkinterval) <= CURRENT_TIME)) - printk ("EXT2-fs warning: checktime reached, " - "running e2fsck is recommended\n"); - es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) & ~EXT2_VALID_FS); - if (!(__s16) le16_to_cpu(es->s_max_mnt_count)) - es->s_max_mnt_count = (__s16) cpu_to_le16(EXT2_DFL_MAX_MNT_COUNT); - es->s_mnt_count=cpu_to_le16(le16_to_cpu(es->s_mnt_count) + 1); - es->s_mtime = cpu_to_le32(CURRENT_TIME); - mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1); - sb->s_dirt = 1; - if (test_opt (sb, DEBUG)) - printk ("[EXT II FS %s, %s, bs=%lu, fs=%lu, gc=%lu, " - "bpg=%lu, ipg=%lu, mo=%04lx]\n", - EXT2FS_VERSION, EXT2FS_DATE, sb->s_blocksize, - sb->u.ext2_sb.s_frag_size, - sb->u.ext2_sb.s_groups_count, - EXT2_BLOCKS_PER_GROUP(sb), - EXT2_INODES_PER_GROUP(sb), - sb->u.ext2_sb.s_mount_opt); + if (read_only) + return res; + if (!(sb->u.ext2_sb.s_mount_state & EXT2_VALID_FS)) + printk ("EXT2-fs warning: mounting unchecked fs, " + "running e2fsck is recommended\n"); + else if ((sb->u.ext2_sb.s_mount_state & EXT2_ERROR_FS)) + printk ("EXT2-fs warning: mounting fs with errors, " + "running e2fsck is recommended\n"); + else if ((__s16) le16_to_cpu(es->s_max_mnt_count) >= 0 && + le16_to_cpu(es->s_mnt_count) >= + (unsigned short) (__s16) le16_to_cpu(es->s_max_mnt_count)) + printk ("EXT2-fs warning: maximal mount count reached, " + "running e2fsck is recommended\n"); + else if (le32_to_cpu(es->s_checkinterval) && + (le32_to_cpu(es->s_lastcheck) + le32_to_cpu(es->s_checkinterval) <= CURRENT_TIME)) + printk ("EXT2-fs warning: checktime reached, " + "running e2fsck is recommended\n"); + es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) & ~EXT2_VALID_FS); + if (!(__s16) le16_to_cpu(es->s_max_mnt_count)) + es->s_max_mnt_count = (__s16) cpu_to_le16(EXT2_DFL_MAX_MNT_COUNT); + es->s_mnt_count=cpu_to_le16(le16_to_cpu(es->s_mnt_count) + 1); + es->s_mtime = cpu_to_le32(CURRENT_TIME); + mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1); + sb->s_dirt = 1; + if (test_opt (sb, DEBUG)) + printk ("[EXT II FS %s, %s, bs=%lu, fs=%lu, gc=%lu, " + "bpg=%lu, ipg=%lu, mo=%04lx]\n", + EXT2FS_VERSION, EXT2FS_DATE, sb->s_blocksize, + sb->u.ext2_sb.s_frag_size, + sb->u.ext2_sb.s_groups_count, + EXT2_BLOCKS_PER_GROUP(sb), + EXT2_INODES_PER_GROUP(sb), + sb->u.ext2_sb.s_mount_opt); #ifdef CONFIG_EXT2_CHECK - if (test_opt (sb, CHECK)) { - ext2_check_blocks_bitmap (sb); - ext2_check_inodes_bitmap (sb); - } -#endif + if (test_opt (sb, CHECK)) { + ext2_check_blocks_bitmap (sb); + ext2_check_inodes_bitmap (sb); } +#endif + return res; } static int ext2_check_descriptors (struct super_block * sb) @@ -601,7 +604,7 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, printk ("EXT2-fs: get root inode failed\n"); return NULL; } - ext2_setup_super (sb, es); + ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY); return sb; } @@ -685,8 +688,8 @@ int ext2_remount (struct super_block * sb, int * flags, char * data) * by e2fsck since we originally mounted the partition.) */ sb->u.ext2_sb.s_mount_state = le16_to_cpu(es->s_state); - sb->s_flags &= ~MS_RDONLY; - ext2_setup_super (sb, es); + if (!ext2_setup_super (sb, es, 0)) + sb->s_flags &= ~MS_RDONLY; } return 0; } diff --git a/fs/fat/dir.c b/fs/fat/dir.c index c7ea5cfe5..bbb895285 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c @@ -10,7 +10,7 @@ * VFAT extensions by Gordon Chaffee <chaffee@plateau.cs.berkeley.edu> * Merged with msdos fs by Henrik Storner <storner@osiris.ping.dk> * Rewritten for constant inumbers. Plugged buffer overrun in readdir(). AV - * Short name translation 1999 by Wolfram Pienkoss <wp@bsz.shk.th.schule.de> + * Short name translation 1999 by Wolfram Pienkoss <wp@bszh.de> */ #define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S)) diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c index 3895b0774..b3fcf2088 100644 --- a/fs/vfat/namei.c +++ b/fs/vfat/namei.c @@ -9,7 +9,7 @@ * what file operation caused you trouble and if you can duplicate * the problem, send a script that demonstrates it. * - * Short name translation 1999 by Wolfram Pienkoss <wp@bsz.shk.th.schule.de> + * Short name translation 1999 by Wolfram Pienkoss <wp@bszh.de> */ #define __NO_VERSION__ diff --git a/include/asm-alpha/cache.h b/include/asm-alpha/cache.h index d9483efb1..e6d4d1695 100644 --- a/include/asm-alpha/cache.h +++ b/include/asm-alpha/cache.h @@ -8,12 +8,14 @@ /* Bytes per L1 (data) cache line. */ #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EV6) -# define L1_CACHE_BYTES 32 /* should be 64, but networking dies */ +# define L1_CACHE_BYTES 64 +# define L1_CACHE_SHIFT 6 #else /* Both EV4 and EV5 are write-through, read-allocate, direct-mapped, physical. */ # define L1_CACHE_BYTES 32 +# define L1_CACHE_SHIFT 5 #endif #define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1)) diff --git a/include/linux/arcdevice.h b/include/linux/arcdevice.h index 63edac9d6..dd88e8a80 100644 --- a/include/linux/arcdevice.h +++ b/include/linux/arcdevice.h @@ -76,7 +76,7 @@ #define D_TIMING 4096 /* show time needed to copy buffers to card */ #ifndef ARCNET_DEBUG_MAX -#define ARCNET_DEBUG_MAX (~0) /* enable ALL debug messages */ +#define ARCNET_DEBUG_MAX (127) /* change to ~0 if you want detailed debugging */ #endif #ifndef ARCNET_DEBUG diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index 0644ae74c..062e310ee 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -11,13 +11,16 @@ */ #define MAX_ARG_PAGES 32 +/* sizeof(linux_binprm->buf) */ +#define BINPRM_BUF_SIZE 128 + #ifdef __KERNEL__ /* * This structure is used to hold the arguments that are used when loading binaries. */ struct linux_binprm{ - char buf[128]; + char buf[BINPRM_BUF_SIZE]; struct page *page[MAX_ARG_PAGES]; unsigned long p; /* current top of mem */ int sh_bang; diff --git a/include/linux/module.h b/include/linux/module.h index a561f805f..fef8d2b20 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -143,8 +143,13 @@ struct module_info #define __MODULE_STRING(x) __MODULE_STRING_1(x) /* Find a symbol exported by the kernel or another module */ +#ifdef CONFIG_MODULES extern unsigned long get_module_symbol(char *, char *); extern void put_module_symbol(unsigned long); +#else +static inline unsigned long get_module_symbol(char *unused1, char *unused2) { return 0; }; +static inline void put_module_symbol(unsigned long unused) { }; +#endif extern int try_inc_mod_count(struct module *mod); diff --git a/include/linux/sched.h b/include/linux/sched.h index 6b82d6977..d6daffe8d 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -243,10 +243,24 @@ struct signal_struct { /* * Some day this will be a full-fledged user tracking system.. - * Right now it is only used to track how many processes a - * user has, but it has the potential to track memory usage etc. */ -struct user_struct; +struct user_struct { + atomic_t __count; /* reference count */ + atomic_t processes; /* How many processes does this user have? */ + atomic_t files; /* How many open files does this user have? */ + + /* Hash table maintenance information */ + struct user_struct *next, **pprev; + unsigned int uid; +}; + +#define get_current_user() ({ \ + struct user_struct *__user = current->user; \ + atomic_inc(&__user->__count); \ + __user; }) + +extern struct user_struct root_user; +#define INIT_USER (&root_user) struct task_struct { /* @@ -427,6 +441,7 @@ struct task_struct { cap_permitted: CAP_FULL_SET, \ keep_capabilities: 0, \ rlim: INIT_RLIMITS, \ + user: INIT_USER, \ comm: "swapper", \ thread: INIT_THREAD, \ fs: &init_fs, \ @@ -489,8 +504,8 @@ static inline struct task_struct *find_task_by_pid(int pid) } /* per-UID process charging. */ -extern int alloc_uid(struct task_struct *); -void free_uid(struct task_struct *); +extern struct user_struct * alloc_uid(uid_t); +extern void free_uid(struct user_struct *); #include <asm/current.h> diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index 86fce1e7d..8ba581f5b 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h @@ -118,6 +118,7 @@ typedef struct { #define RW_LOCK_UNLOCKED (rwlock_t) { 0 } #endif +#define rwlock_init(lock) do { } while(0) #define read_lock(lock) (void)(lock) /* Not "unused variable". */ #define read_unlock(lock) do { } while(0) #define write_lock(lock) (void)(lock) /* Not "unused variable". */ diff --git a/include/scsi/sg.h b/include/scsi/sg.h index 680069a44..060d5de24 100644 --- a/include/scsi/sg.h +++ b/include/scsi/sg.h @@ -11,9 +11,11 @@ Original driver (sg.h): Version 2 and 3 extensions to driver: * Copyright (C) 1998 - 2000 Douglas Gilbert - Version: 3.1.15 (20000528) + Version: 3.1.16 (20000716) This version is for 2.3/2.4 series kernels. + Changes since 3.1.15 (20000528) + - further (scatter gather) buffer length changes Changes since 3.1.14 (20000503) - fix aha1542 odd length buffer problem - make multiple readers on same fd safe diff --git a/kernel/Makefile b/kernel/Makefile index 53606a359..a13812119 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -10,7 +10,7 @@ O_TARGET := kernel.o O_OBJS = sched.o dma.o fork.o exec_domain.o panic.o printk.o \ module.o exit.o itimer.o info.o time.o softirq.o resource.o \ - sysctl.o acct.o capability.o ptrace.o timer.o + sysctl.o acct.o capability.o ptrace.o timer.o user.o OX_OBJS += signal.o sys.o diff --git a/kernel/exit.c b/kernel/exit.c index 89dcd1a3b..993ba31f3 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -38,7 +38,8 @@ void release(struct task_struct * p) spin_unlock_irq(&runqueue_lock); } while (has_cpu); #endif - free_uid(p); + atomic_dec(&p->user->processes); + free_uid(p->user); unhash_process(p); release_thread(p); diff --git a/kernel/fork.c b/kernel/fork.c index 683f047ad..594ee79f3 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -37,125 +37,6 @@ kmem_cache_t *mm_cachep; struct task_struct *pidhash[PIDHASH_SZ]; -/* UID task count cache, to prevent walking entire process list every - * single fork() operation. - */ -#define UIDHASH_SZ (PIDHASH_SZ >> 2) - -static struct user_struct { - atomic_t count; - struct user_struct *next, **pprev; - unsigned int uid; -} *uidhash[UIDHASH_SZ]; - -spinlock_t uidhash_lock = SPIN_LOCK_UNLOCKED; - -kmem_cache_t *uid_cachep; - -#define uidhashfn(uid) (((uid >> 8) ^ uid) & (UIDHASH_SZ - 1)) - -/* - * These routines must be called with the uidhash spinlock held! - */ -static inline void uid_hash_insert(struct user_struct *up, unsigned int hashent) -{ - if((up->next = uidhash[hashent]) != NULL) - uidhash[hashent]->pprev = &up->next; - up->pprev = &uidhash[hashent]; - uidhash[hashent] = up; -} - -static inline void uid_hash_remove(struct user_struct *up) -{ - if(up->next) - up->next->pprev = up->pprev; - *up->pprev = up->next; -} - -static inline struct user_struct *uid_hash_find(unsigned short uid, unsigned int hashent) -{ - struct user_struct *up, *next; - - next = uidhash[hashent]; - for (;;) { - up = next; - if (next) { - next = up->next; - if (up->uid != uid) - continue; - atomic_inc(&up->count); - } - break; - } - return up; -} - -/* - * For SMP, we need to re-test the user struct counter - * after having aquired the spinlock. This allows us to do - * the common case (not freeing anything) without having - * any locking. - */ -#ifdef CONFIG_SMP - #define uid_hash_free(up) (!atomic_read(&(up)->count)) -#else - #define uid_hash_free(up) (1) -#endif - -void free_uid(struct task_struct *p) -{ - struct user_struct *up = p->user; - - if (up) { - p->user = NULL; - if (atomic_dec_and_test(&up->count)) { - spin_lock(&uidhash_lock); - if (uid_hash_free(up)) { - uid_hash_remove(up); - kmem_cache_free(uid_cachep, up); - } - spin_unlock(&uidhash_lock); - } - } -} - -int alloc_uid(struct task_struct *p) -{ - unsigned int hashent = uidhashfn(p->uid); - struct user_struct *up; - - spin_lock(&uidhash_lock); - up = uid_hash_find(p->uid, hashent); - spin_unlock(&uidhash_lock); - - if (!up) { - struct user_struct *new; - - new = kmem_cache_alloc(uid_cachep, SLAB_KERNEL); - if (!new) - return -EAGAIN; - new->uid = p->uid; - atomic_set(&new->count, 1); - - /* - * Before adding this, check whether we raced - * on adding the same user already.. - */ - spin_lock(&uidhash_lock); - up = uid_hash_find(p->uid, hashent); - if (up) { - kmem_cache_free(uid_cachep, new); - } else { - uid_hash_insert(new, hashent); - up = new; - } - spin_unlock(&uidhash_lock); - - } - p->user = up; - return 0; -} - void add_wait_queue(wait_queue_head_t *q, wait_queue_t * wait) { unsigned long flags; @@ -185,17 +66,6 @@ void remove_wait_queue(wait_queue_head_t *q, wait_queue_t * wait) void __init fork_init(unsigned long mempages) { - int i; - - uid_cachep = kmem_cache_create("uid_cache", sizeof(struct user_struct), - 0, - SLAB_HWCACHE_ALIGN, NULL, NULL); - if(!uid_cachep) - panic("Cannot create uid taskcount SLAB cache\n"); - - for(i = 0; i < UIDHASH_SZ; i++) - uidhash[i] = 0; - /* * The default maximum number of threads is set to a safe * value: the thread structures can take up at most half @@ -664,11 +534,10 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs) lock_kernel(); retval = -EAGAIN; - if (p->user) { - if (atomic_read(&p->user->count) >= p->rlim[RLIMIT_NPROC].rlim_cur) - goto bad_fork_free; - atomic_inc(&p->user->count); - } + if (atomic_read(&p->user->processes) >= p->rlim[RLIMIT_NPROC].rlim_cur) + goto bad_fork_free; + atomic_inc(&p->user->__count); + atomic_inc(&p->user->processes); /* * Counter increases are protected by @@ -801,8 +670,8 @@ bad_fork_cleanup: if (p->binfmt && p->binfmt->module) __MOD_DEC_USE_COUNT(p->binfmt->module); bad_fork_cleanup_count: - if (p->user) - free_uid(p); + atomic_dec(&p->user->processes); + free_uid(p->user); bad_fork_free: free_task_struct(p); goto bad_fork; diff --git a/kernel/sys.c b/kernel/sys.c index 2e6b84fa7..0f3181f70 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -466,6 +466,28 @@ extern inline void cap_emulate_setxuid(int old_ruid, int old_euid, } } +static int set_user(uid_t new_ruid) +{ + struct user_struct *new_user, *old_user; + + /* What if a process setreuid()'s and this brings the + * new uid over his NPROC rlimit? We can check this now + * cheaply with the new uid cache, so if it matters + * we should be checking for it. -DaveM + */ + new_user = alloc_uid(new_ruid); + if (!new_user) + return -EAGAIN; + old_user = current->user; + atomic_dec(&old_user->processes); + atomic_inc(&new_user->processes); + + current->uid = new_ruid; + current->user = new_user; + free_uid(old_user); + return 0; +} + /* * Unprivileged users may change the real uid to the effective uid * or vice versa. (BSD-style) @@ -483,28 +505,33 @@ extern inline void cap_emulate_setxuid(int old_ruid, int old_euid, */ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid) { - int old_ruid, old_euid, old_suid, new_ruid; + int old_ruid, old_euid, old_suid, new_ruid, new_euid; new_ruid = old_ruid = current->uid; - old_euid = current->euid; + new_euid = old_euid = current->euid; old_suid = current->suid; + if (ruid != (uid_t) -1) { - if ((old_ruid == ruid) || - (current->euid==ruid) || - capable(CAP_SETUID)) - new_ruid = ruid; - else + new_ruid = ruid; + if ((old_ruid != ruid) && + (current->euid != ruid) && + !capable(CAP_SETUID)) return -EPERM; } + if (euid != (uid_t) -1) { - if ((old_ruid == euid) || - (current->euid == euid) || - (current->suid == euid) || - capable(CAP_SETUID)) - current->fsuid = current->euid = euid; - else + new_euid = euid; + if ((old_ruid != euid) && + (current->euid != euid) && + (current->suid != euid) && + !capable(CAP_SETUID)) return -EPERM; } + + if (new_ruid != old_ruid && set_user(new_ruid) < 0) + return -EAGAIN; + + current->fsuid = current->euid = new_euid; if (ruid != (uid_t) -1 || (euid != (uid_t) -1 && euid != old_ruid)) current->suid = current->euid; @@ -512,17 +539,6 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid) if (current->euid != old_euid) current->dumpable = 0; - if(new_ruid != old_ruid) { - /* What if a process setreuid()'s and this brings the - * new uid over his NPROC rlimit? We can check this now - * cheaply with the new uid cache, so if it matters - * we should be checking for it. -DaveM - */ - free_uid(current); - current->uid = new_ruid; - alloc_uid(current); - } - if (!issecure(SECURE_NO_SETUID_FIXUP)) { cap_emulate_setxuid(old_ruid, old_euid, old_suid); } @@ -550,22 +566,22 @@ asmlinkage long sys_setuid(uid_t uid) old_ruid = new_ruid = current->uid; old_suid = current->suid; - if (capable(CAP_SETUID)) - new_ruid = current->euid = current->suid = current->fsuid = uid; - else if ((uid == current->uid) || (uid == current->suid)) - current->fsuid = current->euid = uid; - else + if (capable(CAP_SETUID)) { + if (uid != old_ruid && set_user(uid) < 0) + return -EAGAIN; + current->suid = uid; + } else if (uid == current->uid) { + /* Nothing - just set fsuid/euid */ + } else if (uid == current->suid) { + if (set_user(uid) < 0) + return -EAGAIN; + } else return -EPERM; - if (current->euid != old_euid) - current->dumpable = 0; + current->fsuid = current->euid = uid; - if (new_ruid != old_ruid) { - /* See comment above about NPROC rlimit issues... */ - free_uid(current); - current->uid = new_ruid; - alloc_uid(current); - } + if (old_euid != uid) + current->dumpable = 0; if (!issecure(SECURE_NO_SETUID_FIXUP)) { cap_emulate_setxuid(old_ruid, old_euid, old_suid); @@ -597,10 +613,8 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) return -EPERM; } if (ruid != (uid_t) -1) { - /* See above commentary about NPROC rlimit issues here. */ - free_uid(current); - current->uid = ruid; - alloc_uid(current); + if (ruid != current->uid && set_user(ruid) < 0) + return -EAGAIN; } if (euid != (uid_t) -1) { if (euid != current->euid) diff --git a/kernel/user.c b/kernel/user.c new file mode 100644 index 000000000..d9f96da0a --- /dev/null +++ b/kernel/user.c @@ -0,0 +1,154 @@ +/* + * The "user cache". + * + * (C) Copyright 1991-2000 Linus Torvalds + * + * We have a per-user structure to keep track of how many + * processes, files etc the user has claimed, in order to be + * able to have per-user limits for system resources. + */ + +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/slab.h> + +/* + * UID task count cache, to get fast user lookup in "alloc_uid" + * when changing user ID's (ie setuid() and friends). + */ +#define UIDHASH_SZ (256) + +static struct user_struct *uidhash[UIDHASH_SZ]; + +spinlock_t uidhash_lock = SPIN_LOCK_UNLOCKED; + +struct user_struct root_user = { + __count: ATOMIC_INIT(1), + processes: ATOMIC_INIT(1), + files: ATOMIC_INIT(0) +}; + +static kmem_cache_t *uid_cachep; + +#define uidhashfn(uid) (((uid >> 8) ^ uid) & (UIDHASH_SZ - 1)) + +/* + * These routines must be called with the uidhash spinlock held! + */ +static inline void uid_hash_insert(struct user_struct *up, unsigned int hashent) +{ + if((up->next = uidhash[hashent]) != NULL) + uidhash[hashent]->pprev = &up->next; + up->pprev = &uidhash[hashent]; + uidhash[hashent] = up; +} + +static inline void uid_hash_remove(struct user_struct *up) +{ + if(up->next) + up->next->pprev = up->pprev; + *up->pprev = up->next; +} + +static inline struct user_struct *uid_hash_find(unsigned short uid, unsigned int hashent) +{ + struct user_struct *up, *next; + + next = uidhash[hashent]; + for (;;) { + up = next; + if (next) { + next = up->next; + if (up->uid != uid) + continue; + atomic_inc(&up->__count); + } + break; + } + return up; +} + +/* + * For SMP, we need to re-test the user struct counter + * after having aquired the spinlock. This allows us to do + * the common case (not freeing anything) without having + * any locking. + */ +#ifdef CONFIG_SMP + #define uid_hash_free(up) (!atomic_read(&(up)->__count)) +#else + #define uid_hash_free(up) (1) +#endif + +void free_uid(struct user_struct *up) +{ + if (up) { + if (atomic_dec_and_test(&up->__count)) { + spin_lock(&uidhash_lock); + if (uid_hash_free(up)) { + uid_hash_remove(up); + kmem_cache_free(uid_cachep, up); + } + spin_unlock(&uidhash_lock); + } + } +} + +struct user_struct * alloc_uid(uid_t uid) +{ + unsigned int hashent = uidhashfn(uid); + struct user_struct *up; + + spin_lock(&uidhash_lock); + up = uid_hash_find(uid, hashent); + spin_unlock(&uidhash_lock); + + if (!up) { + struct user_struct *new; + + new = kmem_cache_alloc(uid_cachep, SLAB_KERNEL); + if (!new) + return NULL; + new->uid = uid; + atomic_set(&new->__count, 1); + atomic_set(&new->processes, 0); + atomic_set(&new->files, 0); + + /* + * Before adding this, check whether we raced + * on adding the same user already.. + */ + spin_lock(&uidhash_lock); + up = uid_hash_find(uid, hashent); + if (up) { + kmem_cache_free(uid_cachep, new); + } else { + uid_hash_insert(new, hashent); + up = new; + } + spin_unlock(&uidhash_lock); + + } + return up; +} + + +static int __init uid_cache_init(void) +{ + int i; + + uid_cachep = kmem_cache_create("uid_cache", sizeof(struct user_struct), + 0, + SLAB_HWCACHE_ALIGN, NULL, NULL); + if(!uid_cachep) + panic("Cannot create uid taskcount SLAB cache\n"); + + for(i = 0; i < UIDHASH_SZ; i++) + uidhash[i] = 0; + + /* Insert the root user immediately - init already runs with this */ + uid_hash_insert(&root_user, uidhashfn(0)); + return 0; +} + +module_init(uid_cache_init); @@ -86,18 +86,24 @@ void __init free_area_init_node(int nid, pg_data_t *pgdat, struct page * alloc_pages(int gfp_mask, unsigned long order) { struct page *ret = 0; - unsigned long flags; int startnode, tnode; +#ifndef CONFIG_NUMA + unsigned long flags; static int nextnid = 0; +#endif if (order >= MAX_ORDER) return NULL; +#ifdef CONFIG_NUMA + tnode = numa_node_id(); +#else spin_lock_irqsave(&node_lock, flags); tnode = nextnid; nextnid++; if (nextnid == numnodes) nextnid = 0; spin_unlock_irqrestore(&node_lock, flags); +#endif startnode = tnode; while (tnode < numnodes) { if ((ret = alloc_pages_node(tnode++, gfp_mask, order))) diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index cc4038385..33de64cc9 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c @@ -44,7 +44,7 @@ static struct 0, NULL, { } }, { /* LOCAL_IN */ - { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, + { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, 0, sizeof(struct ip6t_entry), sizeof(struct ip6t_standard), @@ -52,7 +52,7 @@ static struct { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } }, -NF_ACCEPT - 1 } }, /* FORWARD */ - { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, + { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, 0, sizeof(struct ip6t_entry), sizeof(struct ip6t_standard), @@ -60,7 +60,7 @@ static struct { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } }, -NF_ACCEPT - 1 } }, /* LOCAL_OUT */ - { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, + { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, 0, sizeof(struct ip6t_entry), sizeof(struct ip6t_standard), @@ -69,7 +69,7 @@ static struct -NF_ACCEPT - 1 } } }, /* ERROR */ - { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 }, + { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 }, 0, sizeof(struct ip6t_entry), sizeof(struct ip6t_error), diff --git a/net/socket.c b/net/socket.c index 1870a867c..2993991dd 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1667,7 +1667,7 @@ void __init sock_init(void) { int i; - printk(KERN_INFO "Linux NET4.0 for Linux 2.3\n"); + printk(KERN_INFO "Linux NET4.0 for Linux 2.4\n"); printk(KERN_INFO "Based upon Swansea University Computer Society NET3.039\n"); /* |