Commit 8651e2bd authored by James Bottomley's avatar James Bottomley

Merge

parents 5a528e75 f4e15267
Linux I2O Support (c) Copyright 1999 Red Hat Software
and others.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version
2 of the License, or (at your option) any later version.
AUTHORS (so far)
Alan Cox, Building Number Three Ltd.
Core code, SCSI and Block OSMs
Steve Ralston, LSI Logic Corp.
Debugging SCSI and Block OSM
Deepak Saxena, Intel Corp.
Various core/block extensions
/proc interface, bug fixes
Ioctl interfaces for control
Debugging LAN OSM
Philip Rumpf
Fixed assorted dumb SMP locking bugs
Juha Sievanen, University of Helsinki Finland
LAN OSM code
/proc interface to LAN class
Bug fixes
Core code extensions
Auvo Häkkinen, University of Helsinki Finland
LAN OSM code
/Proc interface to LAN class
Bug fixes
Core code extensions
Taneli Vähäkangas, University of Helsinki Finland
Fixes to i2o_config
CREDITS
This work was made possible by
Red Hat Software
Funding for the Building #3 part of the project
Symbios Logic (Now LSI)
Host adapters, hints, known to work platforms when I hit
compatibility problems
BoxHill Corporation
Loan of initial FibreChannel disk array used for development work.
European Comission
Funding the work done by the University of Helsinki
SysKonnect
Loan of FDDI and Gigabit Ethernet cards
ASUSTeK
Loan of I2O motherboard
This diff is collapsed.
### Version 2.00.3
Wed Jan 29 09:13:44 EST 200 - Atul Mukker <atulm@lsil.com>
i. Change the handshake in ISR while acknowledging interrupts. Write the
valid interrupt pattern 0x10001234 as soon as it is read from the
outdoor register. In existing driver and on certain platform, invalid
command ids were being returned.
Release Date : Thu Aug 19 09:58:33 EDT 2004 - Atul Mukker <atulm@lsil.com>
Current Version : 2.20.3.0 (scsi module), 2.20.2.0 (cmm module)
Older Version : 2.20.2.0 (scsi module), 2.20.1.0 (cmm module)
Also, do not wait on status be become 0xFF, since FW can return this
status in certain circumstances.
i. When copying the mailbox packets, copy only first 14 bytes (for 32-bit
mailboxes) and only first 22 bytes (for 64-bit mailboxes). This is to
avoid getting the stale values for busy bit. We want to set the busy
bit just before issuing command to the FW.
Initialize the numstatus field of mailbox to 0xFF so that we can wait
on this wait in next interrupt. Firmware does not change its value
unless there are some status to be posted
ii. In the reset handling, if the reseted command is not owned by the
driver, do not (wrongly) print information for the "attached" driver
packet.
ii. Specify the logical drive number while issuing the RESERVATION_STATUS
iii. Have extended wait when issuing command in synchronous mode. This is
required for the cases where the option ROM is disabled and there is
no BIOS to start the controller. The FW starts to boot after receiving
the first command from the driver. The current driver has 1 second
timeout for the synchronous commands, which is far less than what is
actually required. We now wait up to MBOX_RESET_TIME (180 seconds) for
FW boot process.
iii. Reduce the default mailbox busy wait time from 300us to 10us. This is
done to avaoid a possible deadlock in FW because of longer bust waits.
iv. In megaraid_mbox_product_info, clear the mailbox contents completely
before preparing the command for inquiry3. This is to ensure that the
FW does not get junk values in the command.
iv. The max outstanding commands are reduced to 126 because that't the
safest value on all FW.
v. Do away with the redundant LSI_CONFIG_COMPAT redefinition for
CONFIG_COMPAT. Replace <asm/ioctl32.h> with <linux/ioctl32.h>
v. Number of sectors per IO are reduced to 128 (64kb), becuase FW needs
resources in special circumstances like check consistency, rebuilds
etc.
- James Bottomley <James.Bottomley@SteelEye.com>, 08.17.2004
linux-scsi mailing list
vi. max_commands is no longer a module parameter because of iv.
vi. Add support for 64-bit applications. Current drivers assume only
32-bit applications, even on 64-bit platforms. Use the "data" and
"buffer" fields of the mimd_t structure, instead of embedded 32-bit
addresses in application mailbox and passthru structures.
### Version: 2.00.2
i. Intermediate release with kernel specific code
vii. Move the function declarations for the management module from
megaraid_mm.h to megaraid_mm.c
- Andrew Morton <akpm@osdl.org>, 08.19.2004
linux-scsi mailing list
### Version: 2.00.1i
Wed Dec 4 14:34:51 EST 2002 - Atul Mukker <atulm@lsil.com>
i. Making the older IO based controllers to work with this driver
viii. Change default values for MEGARAID_NEWGEN, MEGARAID_MM, and
MEGARAID_MAILBOX to 'n' in Kconfig.megaraid
- Andrew Morton <akpm@osdl.org>, 08.19.2004
linux-scsi mailing list
### Version 2.00.1
Fri Nov 15 10:59:44 EST 2002 - Atul Mukker <atulm@lsil.com>
i. Release host lock before issuing internal command to reset
reservations in megaraid_reset() and reacquire after internal command
is completed.
ix. replace udelay with msleep
x. Typos corrected in comments and whitespace adjustments, explicit
grouping of expressions.
Release Date : Fri Jul 23 15:22:07 EDT 2004 - Atul Mukker <atulm@lsil.com>
Current Version : 2.20.2.0 (scsi module), 2.20.1.0 (cmm module)
Older Version : 2.20.1.0 (scsi module), 2.20.0.0 (cmm module)
i. Add PCI ids for Acer ROMB 2E solution
ii. Add PCI ids for I4
iii. Typo corrected for subsys id for megaraid sata 300-4x
iv. Remove yield() while mailbox handshake in synchronous commands
"My other main gripe is things like this:
+ // wait for maximum 1 second for status to post
+ for (i = 0; i < 40000; i++) {
+ if (mbox->numstatus != 0xFF) break;
+ udelay(25); yield();
+ }
which litter the driver. Use of yield() in drivers is deprecated."
- James Bottomley <James.Bottomley@SteelEye.com>, 07.14.2004
linux-scsi mailing list
v. Remove redundant __megaraid_busywait_mbox routine
vi. Fix bug in the managment module, which causes a system lockup when the
IO module is loaded and then unloaded, followed by executing any
management utility. The current version of management module does not
handle the adapter unregister properly.
Specifically, it still keeps a reference to the unregistered
controllers. To avoid this, the static array adapters has been
replaced by a dynamic list, which gets updated every time an adapter
is added or removed.
Also, during unregistration of the IO module, the resources are
now released in the exact reverse order of the allocation time
sequence.
Release Date : Fri Jun 25 18:58:43 EDT 2004 - Atul Mukker <atulm@lsil.com>
Current Version : 2.20.1.0
Older Version : megaraid 2.20.0.1
i. Stale list pointer in adapter causes kernel panic when module
megaraid_mbox is unloaded
Release Date : Thu Jun 24 20:37:11 EDT 2004 - Atul Mukker <atulm@lsil.com>
Current Version : 2.20.0.1
Older Version : megaraid 2.20.0.00
i. Modules are not 'y' by default, but depend on current definition of
SCSI & PCI.
ii. Redundant structure mraid_driver_t removed.
iii. Miscellaneous indentation and goto/label fixes.
- Christoph Hellwig <hch@infradead.org>, 06.24.2004 linux-scsi
iv. scsi_host_put(), do just before completing HBA shutdown.
Release Date : Mon Jun 21 19:53:54 EDT 2004 - Atul Mukker <atulm@lsil.com>
Current Version : 2.20.0.0
Older Version : megaraid 2.20.0.rc2 and 2.00.3
i. Independent module to interact with userland applications and
multiplex command to low level RAID module(s).
"Shared code in a third module, a "library module", is an acceptable
solution. modprobe automatically loads dependent modules, so users
running "modprobe driver1" or "modprobe driver2" would automatically
load the shared library module."
- Jeff Garzik <jgarzik@pobox.com> 02.25.2004 LKML
"As Jeff hinted, if your userspace<->driver API is consistent between
your new MPT-based RAID controllers and your existing megaraid driver,
then perhaps you need a single small helper module (lsiioctl or some
better name), loaded by both mptraid and megaraid automatically, which
handles registering the /dev/megaraid node dynamically. In this case,
both mptraid and megaraid would register with lsiioctl for each
adapter discovered, and lsiioctl would essentially be a switch,
redirecting userspace tool ioctls to the appropriate driver."
- Matt Domsch <Matt_Domsch@dell.com> 02.25.2004 LKML
ii. Remove C99 initializations from pci_device id.
"pci_id_table_g would be much more readable when not using C99
initializers.
PCI table doesn't change, there's lots of users that prefer the more
readable variant. And it's really far less and much easier to grok
lines without C99 initializers."
- Christoph Hellwig <hch@infradead.org>, 05.28.2004 linux-scsi
iii. Many fixes as suggested by Christoph Hellwig <hch@infradead.org> on
linux-scsi, 05.28.2004
iv. We now support up to 32 parallel ioctl commands instead of current 1.
There is a conscious effort to let memory allocation not fail for ioctl
commands.
v. Do away with internal memory management. Use pci_pool_(create|alloc)
instead.
vi. Kill tasklet when unloading the driver.
vii. Do not use "host_lock', driver has fine-grain locks now to protect all
data structures.
viii. Optimize the build scatter-gather list routine. The callers already
know the data transfer address and length.
ix. Better implementation of error handling and recovery. Driver now
performs extended errors recovery for instances like scsi cable pull.
x. Disassociate the management commands with an overlaid scsi command.
Driver now treats the management packets as special packets and has a
dedicated callback routine.
Notes on Management Module
~~~~~~~~~~~~~~~~~~~~~~~~~~
Overview:
--------
Different classes of controllers from LSI Logic, accept and respond to the
user applications in a similar way. They understand the same firmware control
commands. Furthermore, the applications also can treat different classes of
the controllers uniformly. Hence it is logical to have a single module that
interefaces with the applications on one side and all the low level drivers
on the other.
The advantages, though obvious, are listed for completeness:
i. Avoid duplicate code from the low level drivers.
ii. Unburden the low level drivers from having to export the
character node device and related handling.
iii. Implement any policy mechanisms in one place.
iv. Applications have to interface with only module instead of
multiple low level drivers.
Currently this module (called Common Management Module) is used only to issue
ioctl commands. But this module is envisioned to handle all user space level
interactions. So any 'proc', 'sysfs' implementations will be localized in this
common module.
Credits:
-------
"Shared code in a third module, a "library module", is an acceptable
solution. modprobe automatically loads dependent modules, so users
running "modprobe driver1" or "modprobe driver2" would automatically
load the shared library module."
- Jeff Garzik (jgarzik@pobox.com), 02.25.2004 LKML
"As Jeff hinted, if your userspace<->driver API is consistent between
your new MPT-based RAID controllers and your existing megaraid driver,
then perhaps you need a single small helper module (lsiioctl or some
better name), loaded by both mptraid and megaraid automatically, which
handles registering the /dev/megaraid node dynamically. In this case,
both mptraid and megaraid would register with lsiioctl for each
adapter discovered, and lsiioctl would essentially be a switch,
redirecting userspace tool ioctls to the appropriate driver."
- Matt Domsch, (Matt_Domsch@dell.com), 02.25.2004 LKML
Design:
------
The Common Management Module is implemented in megaraid_mm.[ch] files. This
module acts as a registry for low level hba drivers. The low level drivers
(currently only megaraid) register each controller with the common module.
The applications interface with the common module via the character device
node exported by the module.
The lower level drivers now understand only a new improved ioctl packet called
uioc_t. The management module converts the older ioctl packets from the older
applications into uioc_t. After driver handles the uioc_t, the common module
will convert that back into the old format before returning to applications.
As new applications evolve and replace the old ones, the old packet format
will be retired.
Common module dedicates one uioc_t packet to each controller registered. This
can easily be more than one. But since megaraid is the only low level driver
today, and it can handle only one ioctl, there is no reason to have more. But
as new controller classes get added, this will be tuned appropriately.
......@@ -621,6 +621,8 @@ DC390/AM53C974 SCSI driver
P: Kurt Garloff
M: garloff@suse.de
W: http://www.garloff.de/kurt/linux/dc390/
P: Guennadi Liakhovetski
M: g.liakhovetski@gmx.de
S: Maintained
DECnet NETWORK LAYER
......@@ -952,6 +954,12 @@ L: sensors@stimpy.netroedge.com
W: http://www.lm-sensors.nu/
S: Maintained
I2O
P: Markus Lidel
M: markus.lidel@shadowconnect.com
W: http://i2o.shadowconnect.com/
S: Maintained
i386 BOOT CODE
P: Riley H. Williams
M: Riley@Williams.Name
......
......@@ -537,6 +537,7 @@ int scsi_cmd_ioctl(struct file *file, struct gendisk *bd_disk, unsigned int cmd,
* old junk scsi send command ioctl
*/
case SCSI_IOCTL_SEND_COMMAND:
printk(KERN_WARNING "program %s is using a deprecated SCSI ioctl, please convert it to SG_IO\n", current->comm);
err = -EINVAL;
if (!arg)
break;
......
......@@ -27,39 +27,6 @@ config FUSION_MAX_SGE
necessary (or recommended) unless the user will be running
large I/O's via the raw interface.
config FUSION_ISENSE
tristate "Enhanced SCSI error reporting"
depends on MODULES && FUSION && m
---help---
The isense module (roughly stands for Interpret SENSE data) is
completely optional. It simply provides extra English readable
strings in SCSI Error Report(s) that might be generated from the
Fusion MPT SCSI Host driver, for example when a target device
returns a SCSI check condition on a I/O. Without this module
loaded you might see:
SCSI Error Report =-=-= (ioc0,scsi5:0)
SCSI_Status=02h (CHECK_CONDITION)
Original_CDB[]: 2A 00 00 00 00 41 00 00 02 00
SenseData[12h]: 70 00 02 00 00 00 00 0A 00 00 00 00 04 02 02 00 00 00
SenseKey=2h (NOT READY); FRU=02h
ASC/ASCQ=29h/00h
Where otherwise, if this module had been loaded, you would see:
SCSI Error Report =-=-= (ioc0,scsi5:0)
SCSI_Status=02h (CHECK_CONDITION)
Original_CDB[]: 2A 00 00 00 00 41 00 00 02 00 - "WRITE(10)"
SenseData[12h]: 70 00 02 00 00 00 00 0A 00 00 00 00 04 02 02 00 00 00
SenseKey=2h (NOT READY); FRU=02h
ASC/ASCQ=29h/00h "LOGICAL UNIT NOT READY, INITIALIZING CMD. REQUIRED"
Say M for "Enhanced SCSI error reporting" to compile this optional module,
creating a driver named: isense.
NOTE: Support for building this feature into the kernel is not
available, due to kernel size considerations.
config FUSION_CTL
tristate "Fusion MPT misc device (ioctl) driver"
depends on MODULES && FUSION && m
......
......@@ -48,6 +48,5 @@ EXTRA_CFLAGS += ${MPT_CFLAGS}
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC
obj-$(CONFIG_FUSION) += mptbase.o mptscsih.o
obj-$(CONFIG_FUSION_ISENSE) += isense.o
obj-$(CONFIG_FUSION_CTL) += mptctl.o
obj-$(CONFIG_FUSION_LAN) += mptlan.o
This diff is collapsed.
#!/bin/sh
#
# ascq_tbl.sh - Translate SCSI t10.org's "asc-num.txt" file of
# SCSI Additional Sense Code & Qualifiers (ASC/ASCQ's)
# into something useful in C, creating "ascq_tbl.c" file.
#
#*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*#
PREF_INFILE="t10.org/asc-num.txt" # From SCSI t10.org
PREF_OUTFILE="ascq_tbl.c"
#*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*#
xlate_ascq() {
cat | awk '
BEGIN {
DQ = "\042";
OUTFILE = "'"${PREF_OUTFILE}"'";
TRUE = 1;
FALSE = 0;
#debug = TRUE;
# read and discard all lines up to and including the one that begins
# with the "magic token" of "------- -------------- ---"...
headers_gone = FALSE;
while (!headers_gone) {
if (getline <= 0)
exit 1;
header_line[++hdrs] = $0;
if (debug)
printf("header_line[%d] = :%s:\n", ++hdrs, $0);
if ($0 ~ /^------- -------------- ---/) {
headers_gone = TRUE;
}
}
outcount = 0;
}
(NF > 1) {
++outcount;
if (debug)
printf( "DBG: %s\n", $0 );
ASC[outcount] = substr($0,1,2);
ASCQ[outcount] = substr($0,5,2);
devtypes = substr($0,10,14);
gsub(/ /, ".", devtypes);
DESCRIP[outcount] = substr($0,26);
if (!(devtypes in DevTypesVoodoo)) {
DevTypesVoodoo[devtypes] = ++voodoo;
DevTypesIdx[voodoo] = devtypes;
}
DEVTYPES[outcount] = DevTypesVoodoo[devtypes];
# Handle 0xNN exception stuff...
if (ASCQ[outcount] == "NN" || ASCQ[outcount] == "nn")
ASCQ[outcount] = "FF";
}
END {
printf("#ifndef SCSI_ASCQ_TBL_C_INCLUDED\n") > OUTFILE;
printf("#define SCSI_ASCQ_TBL_C_INCLUDED\n") >> OUTFILE;
printf("\n/* AuToMaGiCaLlY generated from: %s'"${FIN}"'%s\n", DQ, DQ) >> OUTFILE;
printf(" *******************************************************************************\n") >> OUTFILE;
for (i=1; i<=hdrs; i++) {
printf(" * %s\n", header_line[i]) >> OUTFILE;
}
printf(" */\n") >> OUTFILE;
printf("\n") >> OUTFILE;
for (i=1; i<=voodoo; i++) {
printf("static char SenseDevTypes%03d[] = %s%s%s;\n", i, DQ, DevTypesIdx[i], DQ) >> OUTFILE;
}
printf("\nstatic ASCQ_Table_t ASCQ_Table[] = {\n") >> OUTFILE;
for (i=1; i<=outcount; i++) {
printf(" {\n") >> OUTFILE;
printf(" 0x%s, 0x%s,\n", ASC[i], ASCQ[i]) >> OUTFILE;
printf(" SenseDevTypes%03d,\n", DEVTYPES[i]) >> OUTFILE;
printf(" %s%s%s\n", DQ, DESCRIP[i], DQ) >> OUTFILE;
printf(" },\n") >> OUTFILE;
}
printf( "};\n\n" ) >> OUTFILE;
printf( "static int ASCQ_TableSize = %d;\n\n", outcount ) >> OUTFILE;
printf( "Total of %d ASC/ASCQ records generated\n", outcount );
printf("\n#endif\n") >> OUTFILE;
close(OUTFILE);
}'
return
}
#*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*#
# main()
if [ $# -lt 1 ]; then
echo "INFO: No input filename supplied - using: $PREF_INFILE" >&2
FIN=$PREF_INFILE
else
FIN="$1"
if [ "$FIN" != "$PREF_INFILE" ]; then
echo "INFO: Ok, I'll try chewing on '$FIN' for SCSI ASC/ASCQ combos..." >&2
fi
shift
fi
cat $FIN | xlate_ascq
exit 0
/*
* linux/drivers/message/fusion/isense.c
* Little linux driver / shim that interfaces with the Fusion MPT
* Linux base driver to provide english readable strings in SCSI
* Error Report logging output. This module implements SCSI-3
* Opcode lookup and a sorted table of SCSI-3 ASC/ASCQ strings.
*
* Copyright (c) 1991-2004 Steven J. Ralston
* Written By: Steven J. Ralston
* (yes I wrote some of the orig. code back in 1991!)
* (mailto:sjralston1@netscape.net)
* (mailto:mpt_linux_developer@lsil.com)
*
* $Id: isense.c,v 1.33 2002/02/27 18:44:19 sralston Exp $
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
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; version 2 of the License.
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.
NO WARRANTY
THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
solely responsible for determining the appropriateness of using and
distributing the Program and assumes all risks associated with its
exercise of rights under this Agreement, including but not limited to
the risks and costs of program errors, damage to or loss of data,
programs or equipment, and unavailability or interruption of operations.
DISCLAIMER OF LIABILITY
NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <asm/io.h>
#define MODULEAUTHOR "Steven J. Ralston"
#define COPYRIGHT "Copyright (c) 2001-2004 " MODULEAUTHOR
#include "mptbase.h"
#include "isense.h"
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* Private data...
*/
/*
* YIKES! I don't usually #include C source files, but..
* The following #include's pulls in our needed ASCQ_Table[] array,
* ASCQ_TableSz integer, and ScsiOpcodeString[] array!
*/
#include "ascq_tbl.c"
#include "scsiops.c"
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
#define my_NAME "SCSI-3 Opcodes & ASC/ASCQ Strings"
#define my_VERSION MPT_LINUX_VERSION_COMMON
#define MYNAM "isense"
MODULE_AUTHOR(MODULEAUTHOR);
MODULE_DESCRIPTION(my_NAME);
MODULE_LICENSE("GPL");
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
int __init isense_init(void)
{
show_mptmod_ver(my_NAME, my_VERSION);
/*
* Install our handler
*/
if (mpt_register_ascqops_strings(&ASCQ_Table[0], ASCQ_TableSize, ScsiOpcodeString) != 1)
{
printk(KERN_ERR MYNAM ": ERROR: Can't register with Fusion MPT base driver!\n");
return -EBUSY;
}
printk(KERN_INFO MYNAM ": Registered SCSI-3 Opcodes & ASC/ASCQ Strings\n");
return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
static void isense_exit(void)
{
#ifdef MODULE
mpt_deregister_ascqops_strings();
#endif
printk(KERN_INFO MYNAM ": Deregistered SCSI-3 Opcodes & ASC/ASCQ Strings\n");
}
module_init(isense_init);
module_exit(isense_exit);
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
#ifndef ISENSE_H_INCLUDED
#define ISENSE_H_INCLUDED
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
#ifdef __KERNEL__
#include <linux/types.h> /* needed for u8, etc. */
#include <linux/string.h> /* needed for strcat */
#include <linux/kernel.h> /* needed for sprintf */
#else
#ifndef U_STUFF_DEFINED
#define U_STUFF_DEFINED
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
#endif
#endif
#include "scsi3.h" /* needed for all things SCSI */
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* Defines and typedefs...
*/
#ifdef __KERNEL__
#define PrintF(x) printk x
#else
#define PrintF(x) printf x
#endif
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#define RETRY_STATUS ((int) 1)
#define PUT_STATUS ((int) 0)
/*
* A generic structure to hold info about IO request that caused
* a Request Sense to be performed, and the resulting Sense Data.
*/
typedef struct IO_Info
{
char *DevIDStr; /* String of chars which identifies the device. */
u8 *cdbPtr; /* Pointer (Virtual/Logical addr) to CDB bytes of
IO request that caused ContAllegianceCond. */
u8 *sensePtr; /* Pointer (Virtual/Logical addr) to Sense Data
returned by Request Sense operation. */
u8 *dataPtr; /* Pointer (Virtual/Logical addr) to Data buffer
of IO request caused ContAllegianceCondition. */
u8 *inqPtr; /* Pointer (Virtual/Logical addr) to Inquiry Data for
IO *Device* that caused ContAllegianceCondition. */
u8 SCSIStatus; /* SCSI status byte of IO request that caused
Contingent Allegiance Condition. */
u8 DoDisplay; /* Shall we display any messages? */
u16 rsvd_align1;
u32 ComplCode; /* Four-byte OS-dependent completion code. */
u32 NotifyL; /* Four-byte OS-dependent notification field. */
} IO_Info_t;
/*
* SCSI Additional Sense Code and Additional Sense Code Qualifier table.
*/
typedef struct ASCQ_Table
{
u8 ASC;
u8 ASCQ;
char *DevTypes;
char *Description;
} ASCQ_Table_t;
#if 0
/*
* SCSI Opcodes table.
*/
typedef struct SCSI_OPS_Table
{
u8 OpCode;
char *DevTypes;
char *ScsiCmndStr;
} SCSI_OPS_Table_t;
#endif
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* Public entry point prototypes
*/
/* in scsiherr.c, needed by mptscsih.c */
extern int mpt_ScsiHost_ErrorReport(IO_Info_t *ioop);
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
#endif
This diff is collapsed.
......@@ -60,8 +60,6 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include "scsi3.h" /* SCSI defines */
#include "lsi/mpi_type.h"
#include "lsi/mpi.h" /* Fusion MPI(nterface) basic defs */
#include "lsi/mpi_ioc.h" /* Fusion MPT IOC(ontroller) defs */
......@@ -85,8 +83,8 @@
#define COPYRIGHT "Copyright (c) 1999-2004 " MODULEAUTHOR
#endif
#define MPT_LINUX_VERSION_COMMON "3.01.09"
#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.01.09"
#define MPT_LINUX_VERSION_COMMON "3.01.15"
#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.01.15"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
......@@ -403,6 +401,11 @@ typedef struct _ScsiCmndTracker {
void *tail;
} ScsiCmndTracker;
/* VirtDevice negoFlags field */
#define MPT_TARGET_NO_NEGO_WIDE 0x01
#define MPT_TARGET_NO_NEGO_SYNC 0x02
#define MPT_TARGET_NO_NEGO_QAS 0x04
#define MPT_TAPE_NEGO_IDP 0x08
/*
* VirtDevice - FC LUN device or SCSI target device
......@@ -420,8 +423,8 @@ typedef struct _VirtDevice {
u8 bus_id;
u8 minSyncFactor; /* 0xFF is async */
u8 maxOffset; /* 0 if async */
u8 maxWidth; /* 0 if narrow, 1 if wide*/
u8 negoFlags; /* bit field, 0 if WDTR/SDTR/QAS allowed */
u8 maxWidth; /* 0 if narrow, 1 if wide */
u8 negoFlags; /* bit field, see above */
u8 raidVolume; /* set, if RAID Volume */
u8 type; /* byte 0 of Inquiry data */
u8 cflags; /* controller flags */
......@@ -460,10 +463,6 @@ typedef struct _VirtDevice {
#define MPT_TARGET_FLAGS_VALID_56 0x10
#define MPT_TARGET_FLAGS_SAF_TE_ISSUED 0x20
#define MPT_TARGET_NO_NEGO_WIDE 0x01
#define MPT_TARGET_NO_NEGO_SYNC 0x02
#define MPT_TARGET_NO_NEGO_QAS 0x04
typedef struct _VirtDevTracker {
struct _VirtDevice *head;
struct _VirtDevice *tail;
......@@ -523,6 +522,7 @@ typedef struct _MPT_IOCTL {
u8 target; /* target for reset */
void *tmPtr;
struct timer_list TMtimer; /* timer function for this adapter */
struct semaphore sem_ioc;
} MPT_IOCTL;
/*
......@@ -600,25 +600,30 @@ typedef struct _MPT_ADAPTER
int alloc_total;
u32 last_state;
int active;
u8 *fifo_pool; /* dma pool for fifo's */
dma_addr_t fifo_pool_dma;
int fifo_pool_sz; /* allocated size */
u8 *chain_alloc; /* chain buffer alloc ptr */
dma_addr_t chain_alloc_dma;
int chain_alloc_sz;
u8 *reply_alloc; /* Reply frames alloc ptr */
dma_addr_t reply_alloc_dma;
u8 *alloc; /* frames alloc ptr */
dma_addr_t alloc_dma;
u32 alloc_sz;
MPT_FRAME_HDR *reply_frames; /* Reply msg frames - rounded up! */
dma_addr_t reply_frames_dma;
u32 reply_frames_low_dma;
int reply_depth; /* Num Allocated reply frames */
int reply_sz; /* Reply frame size */
int num_chain; /* Number of chain buffers */
/* Pool of buffers for chaining. ReqToChain
* and ChainToChain track index of chain buffers.
* ChainBuffer (DMA) virt/phys addresses.
* FreeChainQ (lock) locking mechanisms.
*/
int *ReqToChain;
int *RequestNB;
int *ChainToChain;
u8 *ChainBuffer;
dma_addr_t ChainBufferDMA;
MPT_Q_TRACKER FreeChainQ;
spinlock_t FreeChainQlock;
CHIP_TYPE chip_type;
/* We (host driver) get to manage our own RequestQueue! */
u8 *req_alloc; /* Request frames alloc ptr */
dma_addr_t req_alloc_dma;
MPT_FRAME_HDR *req_frames; /* Request msg frames - rounded up! */
dma_addr_t req_frames_dma;
MPT_FRAME_HDR *req_frames; /* Request msg frames - rounded up! */
u32 req_frames_low_dma;
int req_depth; /* Number of request frames */
int req_sz; /* Request frame size (bytes) */
......@@ -661,6 +666,7 @@ typedef struct _MPT_ADAPTER
#else
u32 mfcnt;
#endif
u32 NB_for_64_byte_frame;
u32 hs_req[MPT_MAX_FRAME_SIZE/sizeof(u32)];
u16 hs_reply[MPT_MAX_FRAME_SIZE/sizeof(u16)];
IOCFactsReply_t facts;
......@@ -674,8 +680,10 @@ typedef struct _MPT_ADAPTER
u8 FirstWhoInit;
u8 upload_fw; /* If set, do a fw upload */
u8 reload_fw; /* Force a FW Reload on next reset */
u8 pad1[5];
u8 NBShiftFactor; /* NB Shift Factor based on Block Size (Facts) */
u8 pad1[4];
struct list_head list;
struct net_device *netdev;
} MPT_ADAPTER;
......@@ -757,10 +765,10 @@ typedef struct _mpt_sge {
#define dexitprintk(x)
#endif
#ifdef MPT_DEBUG_RESET
#define drsprintk(x) printk x
#if defined MPT_DEBUG_FAIL || defined (MPT_DEBUG_SG)
#define dfailprintk(x) printk x
#else
#define drsprintk(x)
#define dfailprintk(x)
#endif
#ifdef MPT_DEBUG_HANDSHAKE
......@@ -769,11 +777,34 @@ typedef struct _mpt_sge {
#define dhsprintk(x)
#endif
#ifdef MPT_DEBUG_EVENTS
#define devtprintk(x) printk x
#else
#define devtprintk(x)
#endif
#ifdef MPT_DEBUG_RESET
#define drsprintk(x) printk x
#else
#define drsprintk(x)
#endif
//#if defined(MPT_DEBUG) || defined(MPT_DEBUG_MSG_FRAME)
#if defined(MPT_DEBUG_MSG_FRAME)
#define dmfprintk(x) printk x
#define DBG_DUMP_REQUEST_FRAME(mfp) \
{ int i, n = 24; \
u32 *m = (u32 *)(mfp); \
for (i=0; i<n; i++) { \
if (i && ((i%8)==0)) \
printk("\n"); \
printk("%08x ", le32_to_cpu(m[i])); \
} \
printk("\n"); \
}
#else
#define dmfprintk(x)
#define DBG_DUMP_REQUEST_FRAME(mfp)
#endif
#ifdef MPT_DEBUG_IRQ
......@@ -794,13 +825,18 @@ typedef struct _mpt_sge {
#define ddlprintk(x)
#endif
#ifdef MPT_DEBUG_DV
#define ddvprintk(x) printk x
#else
#define ddvprintk(x)
#endif
#ifdef MPT_DEBUG_NEGO
#define dnegoprintk(x) printk x
#else
#define dnegoprintk(x)
#endif
#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
#define ddvtprintk(x) printk x
#else
......@@ -813,10 +849,40 @@ typedef struct _mpt_sge {
#define dctlprintk(x)
#endif
#ifdef MPT_DEBUG_RESET
#ifdef MPT_DEBUG_REPLY
#define dreplyprintk(x) printk x
#else
#define dreplyprintk(x)
#endif
#ifdef MPT_DEBUG_TM
#define dtmprintk(x) printk x
#define DBG_DUMP_TM_REQUEST_FRAME(mfp) \
{ u32 *m = (u32 *)(mfp); \
int i, n = 12; \
printk("TM_REQUEST:\n"); \
for (i=0; i<n; i++) { \
if (i && ((i%8)==0)) \
printk("\n"); \
printk("%08x ", le32_to_cpu(m[i])); \
} \
printk("\n"); \
}
#define DBG_DUMP_TM_REPLY_FRAME(mfp) \
{ u32 *m = (u32 *)(mfp); \
int i, n = (le32_to_cpu(m[0]) & 0x00FF0000) >> 16; \
printk("TM_REPLY MessageLength=%d:\n", n); \
for (i=0; i<n; i++) { \
if (i && ((i%8)==0)) \
printk("\n"); \
printk(" %08x", le32_to_cpu(m[i])); \
} \
printk("\n"); \
}
#else
#define dtmprintk(x)
#define DBG_DUMP_TM_REQUEST_FRAME(mfp)
#define DBG_DUMP_TM_REPLY_FRAME(mfp)
#endif
#ifdef MPT_DEBUG_NEH
......@@ -907,6 +973,10 @@ typedef struct _mpt_sge {
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
#define SCSI_STD_SENSE_BYTES 18
#define SCSI_STD_INQUIRY_BYTES 36
#define SCSI_MAX_INQUIRY_BYTES 96
/*
* MPT_SCSI_HOST defines - Used by the IOCTL and the SCSI drivers
* Private to the driver.
......@@ -950,17 +1020,6 @@ typedef struct _MPT_SCSI_HOST {
int port;
u32 pad0;
struct scsi_cmnd **ScsiLookup;
/* Pool of buffers for chaining. ReqToChain
* and ChainToChain track index of chain buffers.
* ChainBuffer (DMA) virt/phys addresses.
* FreeChainQ (lock) locking mechanisms.
*/
int *ReqToChain;
int *ChainToChain;
u8 *ChainBuffer;
dma_addr_t ChainBufferDMA;
MPT_Q_TRACKER FreeChainQ;
spinlock_t FreeChainQlock;
u32 qtag_tick;
VirtDevice **Targets;
MPT_LOCAL_REPLY *pLocal; /* used for internal commands */
......@@ -976,16 +1035,13 @@ typedef struct _MPT_SCSI_HOST {
MPT_Q_TRACKER taskQ; /* TM request Q */
spinlock_t freedoneQlock;
int taskQcnt;
int num_chain; /* Number of chain buffers */
int max_sge; /* Max No of SGE*/
u8 numTMrequests;
u8 tmPending;
u8 resetPending;
u8 is_spi; /* Parallel SCSI i/f */
u8 negoNvram; /* DV disabled, nego NVRAM */
u8 is_multipath; /* Multi-path compatible */
u8 tmState;
u8 rsvd[1];
u8 rsvd[2];
MPT_FRAME_HDR *tmPtr; /* Ptr to TM request*/
MPT_FRAME_HDR *cmdPtr; /* Ptr to nonOS request */
struct scsi_cmnd *abortSCpnt;
......@@ -1055,10 +1111,8 @@ extern int mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func);
extern void mpt_reset_deregister(int cb_idx);
extern int mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx);
extern void mpt_device_driver_deregister(int cb_idx);
extern int mpt_register_ascqops_strings(void *ascqTable, int ascqtbl_sz, const char **opsTable);
extern void mpt_deregister_ascqops_strings(void);
extern MPT_FRAME_HDR *mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc);
extern void mpt_free_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
extern void mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
extern void mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
extern void mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr);
extern void mpt_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr);
......@@ -1086,10 +1140,6 @@ extern DmpServices_t *DmpService;
extern int mpt_lan_index; /* needed by mptlan.c */
extern int mpt_stm_index; /* needed by mptstm.c */
extern void *mpt_v_ASCQ_TablePtr;
extern const char **mpt_ScsiOpcodesPtr;
extern int mpt_ASCQ_TableSz;
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
#endif /* } __KERNEL__ */
......
......@@ -111,7 +111,6 @@ MODULE_LICENSE("GPL");
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
static int mptctl_id = -1;
static struct semaphore mptctl_syscall_sem_ioc[MPT_MAX_ADAPTERS];
static DECLARE_WAIT_QUEUE_HEAD ( mptctl_wait );
......@@ -140,6 +139,9 @@ static int mptctl_do_reset(unsigned long arg);
static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd);
static int mptctl_hp_targetinfo(unsigned long arg);
static int mptctl_probe(struct pci_dev *, const struct pci_device_id *);
static void mptctl_remove(struct pci_dev *);
/*
* Private function calls.
*/
......@@ -208,10 +210,10 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock)
}
if (nonblock) {
if (down_trylock(&mptctl_syscall_sem_ioc[ioc->id]))
if (down_trylock(&ioc->ioctl->sem_ioc))
rc = -EAGAIN;
} else {
if (down_interruptible(&mptctl_syscall_sem_ioc[ioc->id]))
if (down_interruptible(&ioc->ioctl->sem_ioc))
rc = -ERESTARTSYS;
}
dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down return %d\n", rc));
......@@ -445,7 +447,7 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl)
mptctl_free_tm_flags(ioctl->ioc);
del_timer(&ioctl->TMtimer);
mpt_free_msg_frame(mptctl_id, ioctl->ioc, mf);
mpt_free_msg_frame(ioctl->ioc, mf);
ioctl->tmPtr = NULL;
}
......@@ -520,7 +522,7 @@ mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
if (ioctl && (ioctl->status & MPT_IOCTL_STATUS_TMTIMER_ACTIVE)){
ioctl->status &= ~MPT_IOCTL_STATUS_TMTIMER_ACTIVE;
del_timer(&ioctl->TMtimer);
mpt_free_msg_frame(mptctl_id, ioc, ioctl->tmPtr);
mpt_free_msg_frame(ioc, ioctl->tmPtr);
}
} else {
......@@ -630,8 +632,7 @@ mptctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned
else
ret = -EINVAL;
up(&mptctl_syscall_sem_ioc[iocp->id]);
up(&iocp->ioctl->sem_ioc);
return ret;
}
......@@ -1807,7 +1808,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
struct buflist bufOut; /* data Out buffer */
dma_addr_t dma_addr_in;
dma_addr_t dma_addr_out;
int dir; /* PCI data direction */
int sgSize = 0; /* Num SG elements */
int iocnum, flagsLength;
int sz, rc = 0;
......@@ -2117,9 +2117,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
/* Set up the dataOut memory allocation */
if (karg.dataOutSize > 0) {
dir = PCI_DMA_TODEVICE;
if (karg.dataInSize > 0) {
flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |
MPI_SGE_FLAGS_END_OF_BUFFER |
MPI_SGE_FLAGS_DIRECTION |
mpt_addr_size() )
<< MPI_SGE_FLAGS_SHIFT;
......@@ -2158,7 +2158,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
}
if (karg.dataInSize > 0) {
dir = PCI_DMA_FROMDEVICE;
flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
flagsLength |= karg.dataInSize;
......@@ -2206,7 +2205,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
del_timer(&ioc->ioctl->timer);
ioc->ioctl->status &= ~MPT_IOCTL_STATUS_TIMER_ACTIVE;
ioc->ioctl->status |= MPT_IOCTL_STATUS_TM_FAILED;
mpt_free_msg_frame(mptctl_id, ioc, mf);
mpt_free_msg_frame(ioc, mf);
}
} else {
mpt_put_msg_frame(mptctl_id, ioc, mf);
......@@ -2324,7 +2323,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
* otherwise, failure occured after mf acquired.
*/
if (mf)
mpt_free_msg_frame(mptctl_id, ioc, mf);
mpt_free_msg_frame(ioc, mf);
return rc;
}
......@@ -2738,7 +2737,7 @@ compat_mptfwxfer_ioctl(unsigned int fd, unsigned int cmd,
ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
up(&mptctl_syscall_sem_ioc[iocp->id]);
up(&iocp->ioctl->sem_ioc);
return ret;
}
......@@ -2792,36 +2791,32 @@ compat_mpt_command(unsigned int fd, unsigned int cmd,
*/
ret = mptctl_do_mpt_command (karg, &uarg->MF);
up(&mptctl_syscall_sem_ioc[iocp->id]);
up(&iocp->ioctl->sem_ioc);
return ret;
}
#endif
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
int __init mptctl_init(void)
/*
* mptctl_probe - Installs ioctl devices per bus.
* @pdev: Pointer to pci_dev structure
*
* Returns 0 for success, non-zero for failure.
*
*/
static int
mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
int err;
int i;
int where = 1;
int sz;
u8 *mem;
MPT_ADAPTER *ioc = NULL;
int iocnum;
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
show_mptmod_ver(my_NAME, my_VERSION);
for (i=0; i<MPT_MAX_ADAPTERS; i++) {
sema_init(&mptctl_syscall_sem_ioc[i], 1);
ioc = NULL;
if (((iocnum = mpt_verify_adapter(i, &ioc)) < 0) ||
(ioc == NULL)) {
continue;
}
else {
/* This adapter instance is found.
/*
* Allocate and inite a MPT_IOCTL structure
*/
sz = sizeof (MPT_IOCTL);
......@@ -2840,7 +2835,47 @@ int __init mptctl_init(void)
init_timer (&ioc->ioctl->TMtimer);
ioc->ioctl->TMtimer.data = (unsigned long) ioc->ioctl;
ioc->ioctl->TMtimer.function = mptctl_timer_expired;
}
sema_init(&ioc->ioctl->sem_ioc, 1);
return 0;
out_fail:
mptctl_remove(pdev);
return err;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mptctl_remove - Removed ioctl devices
* @pdev: Pointer to pci_dev structure
*
*
*/
static void
mptctl_remove(struct pci_dev *pdev)
{
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
kfree ( ioc->ioctl );
}
static struct mpt_pci_driver mptctl_driver = {
.probe = mptctl_probe,
.remove = mptctl_remove,
};
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
int __init mptctl_init(void)
{
int err;
int where = 1;
show_mptmod_ver(my_NAME, my_VERSION);
if(mpt_device_driver_register(&mptctl_driver,
MPTCTL_DRIVER) != 0 ) {
dprintk((KERN_INFO MYNAM
": failed to register dd callbacks\n"));
}
#ifdef CONFIG_COMPAT
......@@ -2922,29 +2957,14 @@ int __init mptctl_init(void)
unregister_ioctl32_conversion(HP_GETTARGETINFO);
#endif
for (i=0; i<MPT_MAX_ADAPTERS; i++) {
ioc = NULL;
if (((iocnum = mpt_verify_adapter(i, &ioc)) < 0) ||
(ioc == NULL)) {
continue;
}
else {
if (ioc->ioctl) {
kfree ( ioc->ioctl );
ioc->ioctl = NULL;
}
}
}
mpt_device_driver_deregister(MPTCTL_DRIVER);
return err;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
void mptctl_exit(void)
{
int i;
MPT_ADAPTER *ioc;
int iocnum;
misc_deregister(&mptctl_miscdev);
printk(KERN_INFO MYNAM ": Deregistered /dev/%s @ (major,minor=%d,%d)\n",
mptctl_miscdev.name, MISC_MAJOR, mptctl_miscdev.minor);
......@@ -2957,6 +2977,8 @@ void mptctl_exit(void)
mpt_deregister(mptctl_id);
printk(KERN_INFO MYNAM ": Deregistered from Fusion MPT base driver\n");
mpt_device_driver_deregister(MPTCTL_DRIVER);
#ifdef CONFIG_COMPAT
unregister_ioctl32_conversion(MPTIOCINFO);
unregister_ioctl32_conversion(MPTIOCINFO1);
......@@ -2973,20 +2995,6 @@ void mptctl_exit(void)
unregister_ioctl32_conversion(HP_GETTARGETINFO);
#endif
/* Free allocated memory */
for (i=0; i<MPT_MAX_ADAPTERS; i++) {
ioc = NULL;
if (((iocnum = mpt_verify_adapter(i, &ioc)) < 0) ||
(ioc == NULL)) {
continue;
}
else {
if (ioc->ioctl) {
kfree ( ioc->ioctl );
ioc->ioctl = NULL;
}
}
}
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
......
......@@ -177,11 +177,9 @@ static int LanCtx = -1;
static u32 max_buckets_out = 127;
static u32 tx_max_out_p = 127 - 16;
static struct net_device *mpt_landev[MPT_MAX_ADAPTERS+1];
#ifdef QLOGIC_NAA_WORKAROUND
static struct NAA_Hosed *mpt_bad_naa = NULL;
rwlock_t bad_naa_lock;
rwlock_t bad_naa_lock = RW_LOCK_UNLOCKED;
#endif
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
......@@ -203,7 +201,7 @@ extern int mpt_lan_index;
static int
lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
{
struct net_device *dev = mpt_landev[ioc->id];
struct net_device *dev = ioc->netdev;
int FreeReqFrame = 0;
dioprintk((KERN_INFO MYNAM ": %s/%s: Got reply.\n",
......@@ -336,7 +334,7 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
static int
mpt_lan_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
{
struct net_device *dev = mpt_landev[ioc->id];
struct net_device *dev = ioc->netdev;
struct mpt_lan_priv *priv = netdev_priv(dev);
dlprintk((KERN_INFO MYNAM ": IOC %s_reset routed to LAN driver!\n",
......@@ -1334,7 +1332,7 @@ mpt_lan_post_receive_buckets(void *dev_id)
if (pSimple == NULL) {
/**/ printk (KERN_WARNING MYNAM "/%s: No buckets posted\n",
/**/ __FUNCTION__);
mpt_free_msg_frame(LanCtx, mpt_dev, mf);
mpt_free_msg_frame(mpt_dev, mf);
goto out;
}
......@@ -1451,20 +1449,74 @@ mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum)
return dev;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
static int __init mpt_lan_init (void)
static int
mptlan_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
struct net_device *dev;
MPT_ADAPTER *p;
int i, j;
int i;
show_mptmod_ver(LANAME, LANVER);
for (i = 0; i < ioc->facts.NumberOfPorts; i++) {
printk(KERN_INFO MYNAM ": %s: PortNum=%x, "
"ProtocolFlags=%02Xh (%c%c%c%c)\n",
ioc->name, ioc->pfacts[i].PortNumber,
ioc->pfacts[i].ProtocolFlags,
MPT_PROTOCOL_FLAGS_c_c_c_c(
ioc->pfacts[i].ProtocolFlags));
if (!(ioc->pfacts[i].ProtocolFlags &
MPI_PORTFACTS_PROTOCOL_LAN)) {
printk(KERN_INFO MYNAM ": %s: Hmmm... LAN protocol "
"seems to be disabled on this adapter port!\n",
ioc->name);
continue;
}
#ifdef QLOGIC_NAA_WORKAROUND
/* Init the global r/w lock for the bad_naa list. We want to do this
before any boards are initialized and may be used. */
rwlock_init(&bad_naa_lock);
#endif
dev = mpt_register_lan_device(ioc, i);
if (!dev) {
printk(KERN_ERR MYNAM ": %s: Unable to register "
"port%d as a LAN device\n", ioc->name,
ioc->pfacts[i].PortNumber);
continue;
}
printk(KERN_INFO MYNAM ": %s: Fusion MPT LAN device "
"registered as '%s'\n", ioc->name, dev->name);
printk(KERN_INFO MYNAM ": %s/%s: "
"LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
IOC_AND_NETDEV_NAMES_s_s(dev),
dev->dev_addr[0], dev->dev_addr[1],
dev->dev_addr[2], dev->dev_addr[3],
dev->dev_addr[4], dev->dev_addr[5]);
ioc->netdev = dev;
return 0;
}
return -ENODEV;
}
static void
mptlan_remove(struct pci_dev *pdev)
{
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
struct net_device *dev = ioc->netdev;
if(dev != NULL) {
unregister_netdev(dev);
free_netdev(dev);
}
}
static struct mpt_pci_driver mptlan_driver = {
.probe = mptlan_probe,
.remove = mptlan_remove,
};
static int __init mpt_lan_init (void)
{
show_mptmod_ver(LANAME, LANVER);
if ((LanCtx = mpt_register(lan_reply, MPTLAN_DRIVER)) <= 0) {
printk (KERN_ERR MYNAM ": Failed to register with MPT base driver\n");
......@@ -1476,88 +1528,32 @@ static int __init mpt_lan_init (void)
dlprintk((KERN_INFO MYNAM ": assigned context of %d\n", LanCtx));
if (mpt_reset_register(LanCtx, mpt_lan_ioc_reset) == 0) {
dlprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n"));
} else {
if (mpt_reset_register(LanCtx, mpt_lan_ioc_reset)) {
printk(KERN_ERR MYNAM ": Eieee! unable to register a reset "
"handler with mptbase! The world is at an end! "
"Everything is fading to black! Goodbye.\n");
return -EBUSY;
}
for (j = 0; j < MPT_MAX_ADAPTERS; j++) {
mpt_landev[j] = NULL;
}
list_for_each_entry(p, &ioc_list, list) {
for (i = 0; i < p->facts.NumberOfPorts; i++) {
printk (KERN_INFO MYNAM ": %s: PortNum=%x, ProtocolFlags=%02Xh (%c%c%c%c)\n",
p->name,
p->pfacts[i].PortNumber,
p->pfacts[i].ProtocolFlags,
MPT_PROTOCOL_FLAGS_c_c_c_c(p->pfacts[i].ProtocolFlags));
if (!(p->pfacts[i].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
printk (KERN_INFO MYNAM ": %s: Hmmm... LAN protocol seems to be disabled on this adapter port!\n",
p->name);
continue;
}
dev = mpt_register_lan_device (p, i);
if (!dev) {
printk (KERN_ERR MYNAM ": %s: Unable to register port%d as a LAN device\n",
p->name,
p->pfacts[i].PortNumber);
}
printk (KERN_INFO MYNAM ": %s: Fusion MPT LAN device registered as '%s'\n",
p->name, dev->name);
printk (KERN_INFO MYNAM ": %s/%s: LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
IOC_AND_NETDEV_NAMES_s_s(dev),
dev->dev_addr[0], dev->dev_addr[1],
dev->dev_addr[2], dev->dev_addr[3],
dev->dev_addr[4], dev->dev_addr[5]);
// printk (KERN_INFO MYNAM ": %s/%s: Max_TX_outstanding = %d\n",
// IOC_AND_NETDEV_NAMES_s_s(dev),
// NETDEV_TO_LANPRIV_PTR(dev)->tx_max_out);
j = p->id;
mpt_landev[j] = dev;
dlprintk((KERN_INFO MYNAM "/init: dev_addr=%p, mpt_landev[%d]=%p\n",
dev, j, mpt_landev[j]));
}
}
dlprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n"));
if (mpt_device_driver_register(&mptlan_driver, MPTLAN_DRIVER))
dprintk((KERN_INFO MYNAM ": failed to register dd callbacks\n"));
return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
static void __exit mpt_lan_exit(void)
{
int i;
mpt_device_driver_deregister(MPTLAN_DRIVER);
mpt_reset_deregister(LanCtx);
for (i = 0; mpt_landev[i] != NULL; i++) {
struct net_device *dev = mpt_landev[i];
printk (KERN_INFO ": %s/%s: Fusion MPT LAN device unregistered\n",
IOC_AND_NETDEV_NAMES_s_s(dev));
unregister_netdev(dev);
free_netdev(dev);
mpt_landev[i] = NULL;
}
if (LanCtx >= 0) {
mpt_deregister(LanCtx);
LanCtx = -1;
mpt_lan_index = 0;
}
/* deregister any send/receive handler structs. I2Oism? */
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
module_init(mpt_lan_init);
module_exit(mpt_lan_exit);
......
This diff is collapsed.
This diff is collapsed.
static const char *ScsiOpcodeString[256] = {
"TEST UNIT READY\0\01", /* 00h */
"REWIND\0\002"
"\001REZERO UNIT", /* 01h */
"\0\0", /* 02h */
"REQUEST SENSE\0\01", /* 03h */
"FORMAT UNIT\0\03"
"\001FORMAT MEDIUM\0"
"\002FORMAT", /* 04h */
"READ BLOCK LIMITS\0\1", /* 05h */
"\0\0", /* 06h */
"REASSIGN BLOCKS\0\02"
"\010INITIALIZE ELEMENT STATUS", /* 07h */
"READ(06)\0\04"
"\001READ\0"
"\003RECEIVE\0"
"\011GET MESSAGE(06)", /* 08h */
"\0\0", /* 09h */
"WRITE(06)\0\05"
"\001WRITE\0"
"\002PRINT\0"
"\003SEND(6)\0"
"\011SEND MESSAGE(06)", /* 0Ah */
"SEEK(06)\0\02"
"\003SLEW AND PRINT", /* 0Bh */
"\0\0", /* 0Ch */
"\0\0", /* 0Dh */
"\0\0", /* 0Eh */
"READ REVERSE\0\01", /* 0Fh */
"WRITE FILEMARKS\0\02"
"\003SYNCRONIZE BUFFER", /* 10h */
"SPACE(6)\0\01", /* 11h */
"INQUIRY\0\01", /* 12h */
"VERIFY\0\01", /* 13h */
"RECOVER BUFFERED DATA\0\01", /* 14h */
"MODE SELECT(06)\0\01", /* 15h */
"RESERVE(06)\0\02"
"\010RESERVE ELEMENT(06)", /* 16h */
"RELEASE(06)\0\02"
"\010RELEASE ELEMENT(06)", /* 17h */
"COPY\0\01", /* 18h */
"ERASE\0\01", /* 19h */
"MODE SENSE(06)\0\01", /* 1Ah */
"STOP START UNIT\0\04"
"\001LOAD UNLOAD\0"
"\002STOP PRINT\0"
"\006SCAN\0\002", /* 1Bh */
"RECEIVE DIAGNOSTIC RESULTS\0\01", /* 1Ch */
"SEND DIAGNOSTIC\0\01", /* 1Dh */
"PREVENT ALLOW MEDIUM REMOVAL\0\01", /* 1Eh */
"\0\0", /* 1Fh */
"\0\0", /* 20h */
"\0\0", /* 21h */
"\0\0", /* 22h */
"READ FORMAT CAPACITIES\0\01", /* 23h */
"SET WINDOW\0\01", /* 24h */
"READ CAPACITY\0\03"
"\006GET WINDOW\0"
"\037FREAD CARD CAPACITY", /* 25h */
"\0\0", /* 26h */
"\0\0", /* 27h */
"READ(10)\0\02"
"\011GET MESSAGE(10)", /* 28h */
"READ GENERATION\0\01", /* 29h */
"WRITE(10)\0\03"
"\011SEND(10)\0"
"\011SEND MESSAGE(10)", /* 2Ah */
"SEEK(10)\0\03"
"LOCATE(10)\0"
"POSITION TO ELEMENT", /* 2Bh */
"ERASE(10)\0\01", /* 2Ch */
"READ UPDATED BLOCK\0\01", /* 2Dh */
"WRITE AND VERIFY(10)\0\01", /* 2Eh */
"VERIFY(10)\0\01", /* 2Fh */
"SEARCH DATA HIGH(10)\0\01", /* 30h */
"SEARCH DATA EQUAL(10)\0\02"
"OBJECT POSITION", /* 31h */
"SEARCH DATA LOW(10)\0\01", /* 32h */
"SET LIMITS(10)\0\01", /* 33h */
"PRE-FETCH(10)\0\03"
"READ POSITION\0"
"GET DATA BUFFER STATUS", /* 34h */
"SYNCHRONIZE CACHE(10)\0\01", /* 35h */
"LOCK UNLOCK CACHE(10)\0\01", /* 36h */
"READ DEFECT DATA(10)\0\01", /* 37h */
"MEDIUM SCAN\0\01", /* 38h */
"COMPARE\0\01", /* 39h */
"COPY AND VERIFY\0\01", /* 3Ah */
"WRITE BUFFER\0\01", /* 3Bh */
"READ BUFFER\0\01", /* 3Ch */
"UPDATE BLOCK\0\01", /* 3Dh */
"READ LONG\0\01", /* 3Eh */
"WRITE LONG\0\01", /* 3Fh */
"CHANGE DEFINITION\0\01", /* 40h */
"WRITE SAME(10)\0\01", /* 41h */
"READ SUB-CHANNEL\0\01", /* 42h */
"READ TOC/PMA/ATIP\0\01", /* 43h */
"REPORT DENSITY SUPPORT\0\01", /* 44h */
"READ HEADER\0\01", /* 44h */
"PLAY AUDIO(10)\0\01", /* 45h */
"GET CONFIGURATION\0\01", /* 46h */
"PLAY AUDIO MSF\0\01", /* 47h */
"PLAY AUDIO TRACK INDEX\0\01", /* 48h */
"PLAY TRACK RELATIVE(10)\0\01", /* 49h */
"GET EVENT STATUS NOTIFICATION\0\01", /* 4Ah */
"PAUSE/RESUME\0\01", /* 4Bh */
"LOG SELECT\0\01", /* 4Ch */
"LOG SENSE\0\01", /* 4Dh */
"STOP PLAY/SCAN\0\01", /* 4Eh */
"\0\0", /* 4Fh */
"XDWRITE(10)\0\01", /* 50h */
"XPWRITE(10)\0\02"
"READ DISC INFORMATION", /* 51h */
"XDREAD(10)\0\01"
"READ TRACK INFORMATION", /* 52h */
"RESERVE TRACK\0\01", /* 53h */
"SEND OPC INFORMATION\0\01", /* 54h */
"MODE SELECT(10)\0\01", /* 55h */
"RESERVE(10)\0\02"
"RESERVE ELEMENT(10)", /* 56h */
"RELEASE(10)\0\02"
"RELEASE ELEMENT(10)", /* 57h */
"REPAIR TRACK\0\01", /* 58h */
"READ MASTER CUE\0\01", /* 59h */
"MODE SENSE(10)\0\01", /* 5Ah */
"CLOSE TRACK/SESSION\0\01", /* 5Bh */
"READ BUFFER CAPACITY\0\01", /* 5Ch */
"SEND CUE SHEET\0\01", /* 5Dh */
"PERSISTENT RESERVE IN\0\01", /* 5Eh */
"PERSISTENT RESERVE OUT\0\01", /* 5Fh */
"\0\0", /* 60h */
"\0\0", /* 61h */
"\0\0", /* 62h */
"\0\0", /* 63h */
"\0\0", /* 64h */
"\0\0", /* 65h */
"\0\0", /* 66h */
"\0\0", /* 67h */
"\0\0", /* 68h */
"\0\0", /* 69h */
"\0\0", /* 6Ah */
"\0\0", /* 6Bh */
"\0\0", /* 6Ch */
"\0\0", /* 6Dh */
"\0\0", /* 6Eh */
"\0\0", /* 6Fh */
"\0\0", /* 70h */
"\0\0", /* 71h */
"\0\0", /* 72h */
"\0\0", /* 73h */
"\0\0", /* 74h */
"\0\0", /* 75h */
"\0\0", /* 76h */
"\0\0", /* 77h */
"\0\0", /* 78h */
"\0\0", /* 79h */
"\0\0", /* 7Ah */
"\0\0", /* 7Bh */
"\0\0", /* 7Ch */
"\0\0", /* 7Eh */
"\0\0", /* 7Eh */
"\0\0", /* 7Fh */
"XDWRITE EXTENDED(16)\0\01", /* 80h */
"REBUILD(16)\0\01", /* 81h */
"REGENERATE(16)\0\01", /* 82h */
"EXTENDED COPY\0\01", /* 83h */
"RECEIVE COPY RESULTS\0\01", /* 84h */
"ACCESS CONTROL IN [proposed]\0\01", /* 86h */
"ACCESS CONTROL OUT [proposed]\0\01", /* 87h */
"READ(16)\0\01", /* 88h */
"DEVICE LOCKS [proposed]\0\01", /* 89h */
"WRITE(16)\0\01", /* 8Ah */
"\0\0", /* 8Bh */
"READ ATTRIBUTES [proposed]\0\01", /* 8Ch */
"WRITE ATTRIBUTES [proposed]\0\01", /* 8Dh */
"WRITE AND VERIFY(16)\0\01", /* 8Eh */
"VERIFY(16)\0\01", /* 8Fh */
"PRE-FETCH(16)\0\01", /* 90h */
"SYNCHRONIZE CACHE(16)\0\02"
"SPACE(16) [1]", /* 91h */
"LOCK UNLOCK CACHE(16)\0\02"
"LOCATE(16) [1]", /* 92h */
"WRITE SAME(16)\0\01", /* 93h */
"[usage proposed by SCSI Socket Services project]\0\01", /* 94h */
"[usage proposed by SCSI Socket Services project]\0\01", /* 95h */
"[usage proposed by SCSI Socket Services project]\0\01", /* 96h */
"[usage proposed by SCSI Socket Services project]\0\01", /* 97h */
"MARGIN CONTROL [proposed]\0\01", /* 98h */
"\0\0", /* 99h */
"\0\0", /* 9Ah */
"\0\0", /* 9Bh */
"\0\0", /* 9Ch */
"\0\0", /* 9Dh */
"SERVICE ACTION IN [proposed]\0\01", /* 9Eh */
"SERVICE ACTION OUT [proposed]\0\01", /* 9Fh */
"REPORT LUNS\0\01", /* A0h */
"BLANK\0\01", /* A1h */
"SEND EVENT\0\01", /* A2h */
"MAINTENANCE (IN)\0\02"
"SEND KEY", /* A3h */
"MAINTENANCE (OUT)\0\02"
"REPORT KEY", /* A4h */
"MOVE MEDIUM\0\02"
"PLAY AUDIO(12)", /* A5h */
"EXCHANGE MEDIUM\0\02"
"LOAD/UNLOAD C/DVD", /* A6h */
"MOVE MEDIUM ATTACHED\0\02"
"SET READ AHEAD\0\01", /* A7h */
"READ(12)\0\02"
"GET MESSAGE(12)", /* A8h */
"PLAY TRACK RELATIVE(12)\0\01", /* A9h */
"WRITE(12)\0\02"
"SEND MESSAGE(12)", /* AAh */
"\0\0", /* ABh */
"ERASE(12)\0\02"
"GET PERFORMANCE", /* ACh */
"READ DVD STRUCTURE\0\01", /* ADh */
"WRITE AND VERIFY(12)\0\01", /* AEh */
"VERIFY(12)\0\01", /* AFh */
"SEARCH DATA HIGH(12)\0\01", /* B0h */
"SEARCH DATA EQUAL(12)\0\01", /* B1h */
"SEARCH DATA LOW(12)\0\01", /* B2h */
"SET LIMITS(12)\0\01", /* B3h */
"READ ELEMENT STATUS ATTACHED\0\01", /* B4h */
"REQUEST VOLUME ELEMENT ADDRESS\0\01", /* B5h */
"SEND VOLUME TAG\0\02"
"SET STREAMING", /* B6h */
"READ DEFECT DATA(12)\0\01", /* B7h */
"READ ELEMENT STATUS\0\01", /* B8h */
"READ CD MSF\0\01", /* B9h */
"REDUNDANCY GROUP (IN)\0\02"
"SCAN", /* BAh */
"REDUNDANCY GROUP (OUT)\0\02"
"SET CD-ROM SPEED", /* BBh */
"SPARE (IN)\0\02"
"PLAY CD", /* BCh */
"SPARE (OUT)\0\02"
"MECHANISM STATUS", /* BDh */
"VOLUME SET (IN)\0\02"
"READ CD", /* BEh */
"VOLUME SET (OUT)\0\0\02"
"SEND DVD STRUCTURE", /* BFh */
"\0\0", /* C0h */
"\0\0", /* C1h */
"\0\0", /* C2h */
"\0\0", /* C3h */
"\0\0", /* C4h */
"\0\0", /* C5h */
"\0\0", /* C6h */
"\0\0", /* C7h */
"\0\0", /* C8h */
"\0\0", /* C9h */
"\0\0", /* CAh */
"\0\0", /* CBh */
"\0\0", /* CCh */
"\0\0", /* CDh */
"\0\0", /* CEh */
"\0\0", /* CFh */
"\0\0", /* D0h */
"\0\0", /* D1h */
"\0\0", /* D2h */
"\0\0", /* D3h */
"\0\0", /* D4h */
"\0\0", /* D5h */
"\0\0", /* D6h */
"\0\0", /* D7h */
"\0\0", /* D8h */
"\0\0", /* D9h */
"\0\0", /* DAh */
"\0\0", /* DBh */
"\0\0", /* DCh */
"\0\0", /* DEh */
"\0\0", /* DEh */
"\0\0", /* DFh */
"\0\0", /* E0h */
"\0\0", /* E1h */
"\0\0", /* E2h */
"\0\0", /* E3h */
"\0\0", /* E4h */
"\0\0", /* E5h */
"\0\0", /* E6h */
"\0\0", /* E7h */
"\0\0", /* E8h */
"\0\0", /* E9h */
"\0\0", /* EAh */
"\0\0", /* EBh */
"\0\0", /* ECh */
"\0\0", /* EDh */
"\0\0", /* EEh */
"\0\0", /* EFh */
"\0\0", /* F0h */
"\0\0", /* F1h */
"\0\0", /* F2h */
"\0\0", /* F3h */
"\0\0", /* F4h */
"\0\0", /* F5h */
"\0\0", /* F6h */
"\0\0", /* F7h */
"\0\0", /* F8h */
"\0\0", /* F9h */
"\0\0", /* FAh */
"\0\0", /* FBh */
"\0\0", /* FEh */
"\0\0", /* FEh */
"\0\0", /* FEh */
"\0\0" /* FFh */
};
......@@ -5,6 +5,7 @@
# In the future, some of these should be built conditionally.
#
i2o_core-y += iop.o driver.o device.o debug.o pci.o exec-osm.o
obj-$(CONFIG_I2O) += i2o_core.o
obj-$(CONFIG_I2O_CONFIG)+= i2o_config.o
obj-$(CONFIG_I2O_BLOCK) += i2o_block.o
......
This diff is collapsed.
This diff is collapsed.
/*
* Functions to handle I2O drivers (OSMs) and I2O bus type for sysfs
*
* Copyright (C) 2004 Markus Lidel <Markus.Lidel@shadowconnect.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* Fixes/additions:
* Markus Lidel <Markus.Lidel@shadowconnect.com>
* initial version.
*/
#include <linux/device.h>
#include <linux/module.h>
#include <linux/rwsem.h>
#include <linux/i2o.h>
/* max_drivers - Maximum I2O drivers (OSMs) which could be registered */
unsigned int i2o_max_drivers = I2O_MAX_DRIVERS;
module_param_named(max_drivers, i2o_max_drivers, uint, 0);
MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support");
/* I2O drivers lock and array */
static spinlock_t i2o_drivers_lock = SPIN_LOCK_UNLOCKED;
static struct i2o_driver **i2o_drivers;
/**
* i2o_bus_match - Tell if a I2O device class id match the class ids of
* the I2O driver (OSM)
*
* @dev: device which should be verified
* @drv: the driver to match against
*
* Used by the bus to check if the driver wants to handle the device.
*
* Returns 1 if the class ids of the driver match the class id of the
* device, otherwise 0.
*/
static int i2o_bus_match(struct device *dev, struct device_driver *drv)
{
struct i2o_device *i2o_dev = to_i2o_device(dev);
struct i2o_driver *i2o_drv = to_i2o_driver(drv);
struct i2o_class_id *ids = i2o_drv->classes;
if (ids)
while (ids->class_id != I2O_CLASS_END) {
if (ids->class_id == i2o_dev->lct_data.class_id)
return 1;
ids++;
}
return 0;
};
/* I2O bus type */
struct bus_type i2o_bus_type = {
.name = "i2o",
.match = i2o_bus_match,
};
/**
* i2o_driver_register - Register a I2O driver (OSM) in the I2O core
* @drv: I2O driver which should be registered
*
* Registers the OSM drv in the I2O core and creates an event queues if
* necessary.
*
* Returns 0 on success or negative error code on failure.
*/
int i2o_driver_register(struct i2o_driver *drv)
{
struct i2o_controller *c;
int i;
int rc = 0;
unsigned long flags;
pr_debug("Register driver %s\n", drv->name);
if (drv->event) {
drv->event_queue = create_workqueue(drv->name);
if (!drv->event_queue) {
printk(KERN_ERR "i2o: Could not initialize event queue "
"for driver %s\n", drv->name);
return -EFAULT;
}
pr_debug("Event queue initialized for driver %s\n", drv->name);
} else
drv->event_queue = NULL;
drv->driver.name = drv->name;
drv->driver.bus = &i2o_bus_type;
spin_lock_irqsave(&i2o_drivers_lock, flags);
for (i = 0; i2o_drivers[i]; i++)
if (i >= i2o_max_drivers) {
printk(KERN_ERR "i2o: too many drivers registered, "
"increase max_drivers\n");
spin_unlock_irqrestore(&i2o_drivers_lock, flags);
return -EFAULT;
}
drv->context = i;
i2o_drivers[i] = drv;
spin_unlock_irqrestore(&i2o_drivers_lock, flags);
pr_debug("driver %s gets context id %d\n", drv->name, drv->context);
list_for_each_entry(c, &i2o_controllers, list) {
struct i2o_device *i2o_dev;
i2o_driver_notify_controller_add(drv, c);
list_for_each_entry(i2o_dev, &c->devices, list)
i2o_driver_notify_device_add(drv, i2o_dev);
}
rc = driver_register(&drv->driver);
if (rc)
destroy_workqueue(drv->event_queue);
return rc;
};
/**
* i2o_driver_unregister - Unregister a I2O driver (OSM) from the I2O core
* @drv: I2O driver which should be unregistered
*
* Unregisters the OSM drv from the I2O core and cleanup event queues if
* necessary.
*/
void i2o_driver_unregister(struct i2o_driver *drv)
{
struct i2o_controller *c;
unsigned long flags;
pr_debug("unregister driver %s\n", drv->name);
driver_unregister(&drv->driver);
list_for_each_entry(c, &i2o_controllers, list) {
struct i2o_device *i2o_dev;
list_for_each_entry(i2o_dev, &c->devices, list)
i2o_driver_notify_device_remove(drv, i2o_dev);
i2o_driver_notify_controller_remove(drv, c);
}
spin_lock_irqsave(&i2o_drivers_lock, flags);
i2o_drivers[drv->context] = NULL;
spin_unlock_irqrestore(&i2o_drivers_lock, flags);
if (drv->event_queue) {
destroy_workqueue(drv->event_queue);
drv->event_queue = NULL;
pr_debug("event queue removed for %s\n", drv->name);
}
};
/**
* i2o_driver_dispatch - dispatch an I2O reply message
* @c: I2O controller of the message
* @m: I2O message number
* @msg: I2O message to be delivered
*
* The reply is delivered to the driver from which the original message
* was. This function is only called from interrupt context.
*
* Returns 0 on success and the message should not be flushed. Returns > 0
* on success and if the message should be flushed afterwords. Returns
* negative error code on failure (the message will be flushed too).
*/
int i2o_driver_dispatch(struct i2o_controller *c, u32 m,
struct i2o_message *msg)
{
struct i2o_driver *drv;
u32 context = readl(&msg->u.s.icntxt);
if (likely(context < i2o_max_drivers)) {
spin_lock(&i2o_drivers_lock);
drv = i2o_drivers[context];
spin_unlock(&i2o_drivers_lock);
if (unlikely(!drv)) {
printk(KERN_WARNING "i2o: Spurious reply to unknown "
"driver %d\n", context);
return -EIO;
}
if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) {
struct i2o_device *dev, *tmp;
struct i2o_event *evt;
u16 size;
u16 tid;
tid = readl(&msg->u.head[1]) & 0x1fff;
pr_debug("%s: event received from device %d\n", c->name,
tid);
/* cut of header from message size (in 32-bit words) */
size = (readl(&msg->u.head[0]) >> 16) - 5;
evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC);
if (!evt)
return -ENOMEM;
memset(evt, 0, size * 4 + sizeof(*evt));
evt->size = size;
memcpy_fromio(&evt->tcntxt, &msg->u.s.tcntxt,
(size + 2) * 4);
list_for_each_entry_safe(dev, tmp, &c->devices, list)
if (dev->lct_data.tid == tid) {
evt->i2o_dev = dev;
break;
}
INIT_WORK(&evt->work, (void (*)(void *))drv->event,
evt);
queue_work(drv->event_queue, &evt->work);
return 1;
}
if (likely(drv->reply))
return drv->reply(c, m, msg);
else
pr_debug("%s: Reply to driver %s, but no reply function"
" defined!\n", c->name, drv->name);
return -EIO;
} else
printk(KERN_WARNING "i2o: Spurious reply to unknown driver "
"%d\n", readl(&msg->u.s.icntxt));
return -EIO;
}
/**
* i2o_driver_notify_controller_add_all - Send notify of added controller
* to all I2O drivers
*
* Send notifications to all registered drivers that a new controller was
* added.
*/
void i2o_driver_notify_controller_add_all(struct i2o_controller *c) {
int i;
struct i2o_driver *drv;
for(i = 0; i < I2O_MAX_DRIVERS; i ++) {
drv = i2o_drivers[i];
if(drv)
i2o_driver_notify_controller_add(drv, c);
}
}
/**
* i2o_driver_notify_controller_remove_all - Send notify of removed
* controller to all I2O drivers
*
* Send notifications to all registered drivers that a controller was
* removed.
*/
void i2o_driver_notify_controller_remove_all(struct i2o_controller *c) {
int i;
struct i2o_driver *drv;
for(i = 0; i < I2O_MAX_DRIVERS; i ++) {
drv = i2o_drivers[i];
if(drv)
i2o_driver_notify_controller_remove(drv, c);
}
}
/**
* i2o_driver_notify_device_add_all - Send notify of added device to all
* I2O drivers
*
* Send notifications to all registered drivers that a device was added.
*/
void i2o_driver_notify_device_add_all(struct i2o_device *i2o_dev) {
int i;
struct i2o_driver *drv;
for(i = 0; i < I2O_MAX_DRIVERS; i ++) {
drv = i2o_drivers[i];
if(drv)
i2o_driver_notify_device_add(drv, i2o_dev);
}
}
/**
* i2o_driver_notify_device_remove_all - Send notify of removed device to
* all I2O drivers
*
* Send notifications to all registered drivers that a device was removed.
*/
void i2o_driver_notify_device_remove_all(struct i2o_device *i2o_dev) {
int i;
struct i2o_driver *drv;
for(i = 0; i < I2O_MAX_DRIVERS; i ++) {
drv = i2o_drivers[i];
if(drv)
i2o_driver_notify_device_remove(drv, i2o_dev);
}
}
/**
* i2o_driver_init - initialize I2O drivers (OSMs)
*
* Registers the I2O bus and allocate memory for the array of OSMs.
*
* Returns 0 on success or negative error code on failure.
*/
int __init i2o_driver_init(void)
{
int rc = 0;
if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64) ||
((i2o_max_drivers ^ (i2o_max_drivers - 1)) !=
(2 * i2o_max_drivers - 1))) {
printk(KERN_WARNING "i2o: max_drivers set to %d, but must be "
">=2 and <= 64 and a power of 2\n", i2o_max_drivers);
i2o_max_drivers = I2O_MAX_DRIVERS;
}
printk(KERN_INFO "i2o: max_drivers=%d\n", i2o_max_drivers);
i2o_drivers =
kmalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL);
if (!i2o_drivers)
return -ENOMEM;
memset(i2o_drivers, 0, i2o_max_drivers * sizeof(*i2o_drivers));
rc = bus_register(&i2o_bus_type);
if (rc < 0)
kfree(i2o_drivers);
return rc;
};
/**
* i2o_driver_exit - clean up I2O drivers (OSMs)
*
* Unregisters the I2O bus and free driver array.
*/
void __exit i2o_driver_exit(void)
{
bus_unregister(&i2o_bus_type);
kfree(i2o_drivers);
};
EXPORT_SYMBOL(i2o_driver_register);
EXPORT_SYMBOL(i2o_driver_unregister);
EXPORT_SYMBOL(i2o_driver_notify_controller_add_all);
EXPORT_SYMBOL(i2o_driver_notify_controller_remove_all);
EXPORT_SYMBOL(i2o_driver_notify_device_add_all);
EXPORT_SYMBOL(i2o_driver_notify_device_remove_all);
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -1720,8 +1720,9 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
hostdata->connected = cmd;
hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
if (cmd->SCp.ptr != (char *)cmd->sense_buffer) {
initialize_SCp(cmd);
}
return 0;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment