Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
12c262b2
Commit
12c262b2
authored
Aug 14, 2002
by
James Bottomley
Browse files
Options
Browse Files
Download
Plain Diff
Merge mulgrave.(none):/home/jejb/BK/scsi-cpqfc-2.5
into mulgrave.(none):/home/jejb/BK/scsi-for-linus-2.5
parents
378a8995
bd381b1f
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
226 additions
and
115 deletions
+226
-115
drivers/scsi/cpqfc.Readme
drivers/scsi/cpqfc.Readme
+7
-0
drivers/scsi/cpqfcTSinit.c
drivers/scsi/cpqfcTSinit.c
+173
-95
drivers/scsi/cpqfcTSstructs.h
drivers/scsi/cpqfcTSstructs.h
+14
-3
drivers/scsi/cpqfcTSworker.c
drivers/scsi/cpqfcTSworker.c
+32
-17
No files found.
drivers/scsi/cpqfc.Readme
View file @
12c262b2
...
@@ -7,11 +7,18 @@ Tested in single and dual HBA configuration, 32 and 64bit busses,
...
@@ -7,11 +7,18 @@ Tested in single and dual HBA configuration, 32 and 64bit busses,
SEST size 512 Exchanges (simultaneous I/Os) limited by module kmalloc()
SEST size 512 Exchanges (simultaneous I/Os) limited by module kmalloc()
max of 128k bytes contiguous.
max of 128k bytes contiguous.
Ver 2.5.3 Aug 01, 2002
* fix the passthru ioctl to handle the Scsi_Cmnd->request being a pointer
Ver 2.5.1 Jul 30, 2002
* fix ioctl to pay attention to the specified LUN.
Ver 2.5.0 Nov 29, 2001
Ver 2.5.0 Nov 29, 2001
* eliminated io_request_lock. This change makes the driver specific
* eliminated io_request_lock. This change makes the driver specific
to the 2.5.x kernels.
to the 2.5.x kernels.
* silenced excessively noisy printks.
* silenced excessively noisy printks.
Ver 2.1.2 July 23, 2002
* initialize DumCmnd->lun in cpqfcTS_ioctl (used in fcFindLoggedInPorts as LUN index)
Ver 2.1.1 Oct 18, 2001
Ver 2.1.1 Oct 18, 2001
* reinitialize Cmnd->SCp.sent_command (used to identify commands as
* reinitialize Cmnd->SCp.sent_command (used to identify commands as
passthrus) on calling scsi_done, since the scsi mid layer does not
passthrus) on calling scsi_done, since the scsi mid layer does not
...
...
drivers/scsi/cpqfcTSinit.c
View file @
12c262b2
...
@@ -68,7 +68,7 @@
...
@@ -68,7 +68,7 @@
/* Embedded module documentation macros - see module.h */
/* Embedded module documentation macros - see module.h */
MODULE_AUTHOR
(
"Compaq Computer Corporation"
);
MODULE_AUTHOR
(
"Compaq Computer Corporation"
);
MODULE_DESCRIPTION
(
"Driver for Compaq 64-bit/66Mhz PCI Fibre Channel HBA v. 2.
1.1
"
);
MODULE_DESCRIPTION
(
"Driver for Compaq 64-bit/66Mhz PCI Fibre Channel HBA v. 2.
5.3
"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
int
cpqfcTS_TargetDeviceReset
(
Scsi_Device
*
ScsiDev
,
unsigned
int
reset_flags
);
int
cpqfcTS_TargetDeviceReset
(
Scsi_Device
*
ScsiDev
,
unsigned
int
reset_flags
);
...
@@ -105,15 +105,16 @@ static struct proc_dir_entry proc_scsi_cpqfcTS =
...
@@ -105,15 +105,16 @@ static struct proc_dir_entry proc_scsi_cpqfcTS =
# define CPQFC_WAIT_FOR_COMPLETION(x) down(x)
# define CPQFC_WAIT_FOR_COMPLETION(x) down(x)
#endif
#endif
static
int
cpqfc_alloc_private_data_pool
(
CPQFCHBA
*
hba
);
/* local function to load our per-HBA (local) data for chip
/* local function to load our per-HBA (local) data for chip
registers, FC link state, all FC exchanges, etc.
registers, FC link state, all FC exchanges, etc.
We allocate space and compute address offsets for the
We allocate space and compute address offsets for the
most frequently accessed addresses; others (like World Wide
most frequently accessed addresses; others (like World Wide
Name) are not necessary.
Name) are not necessary.
*/
*/
static
void
Cpqfc_initHBAdata
(
CPQFCHBA
*
cpqfcHBAdata
,
struct
pci_dev
*
PciDev
)
static
void
Cpqfc_initHBAdata
(
CPQFCHBA
*
cpqfcHBAdata
,
struct
pci_dev
*
PciDev
)
{
{
cpqfcHBAdata
->
PciDev
=
PciDev
;
// copy PCI info ptr
cpqfcHBAdata
->
PciDev
=
PciDev
;
// copy PCI info ptr
...
@@ -226,8 +227,11 @@ static void Cpqfc_initHBAdata( CPQFCHBA *cpqfcHBAdata, struct pci_dev *PciDev )
...
@@ -226,8 +227,11 @@ static void Cpqfc_initHBAdata( CPQFCHBA *cpqfcHBAdata, struct pci_dev *PciDev )
cpqfcHBAdata
->
fcChip
.
ReadWriteWWN
=
CpqTsReadWriteWWN
;
cpqfcHBAdata
->
fcChip
.
ReadWriteWWN
=
CpqTsReadWriteWWN
;
cpqfcHBAdata
->
fcChip
.
ReadWriteNVRAM
=
CpqTsReadWriteNVRAM
;
cpqfcHBAdata
->
fcChip
.
ReadWriteNVRAM
=
CpqTsReadWriteNVRAM
;
if
(
cpqfc_alloc_private_data_pool
(
cpqfcHBAdata
)
!=
0
)
{
printk
(
KERN_WARNING
"cpqfc: unable to allocate pool for passthru ioctls. "
"Passthru ioctls disabled.
\n
"
);
}
}
}
...
@@ -483,6 +487,75 @@ static void my_ioctl_done (Scsi_Cmnd * SCpnt)
...
@@ -483,6 +487,75 @@ static void my_ioctl_done (Scsi_Cmnd * SCpnt)
}
}
static
int
cpqfc_alloc_private_data_pool
(
CPQFCHBA
*
hba
)
{
hba
->
private_data_bits
=
NULL
;
hba
->
private_data_pool
=
NULL
;
hba
->
private_data_bits
=
kmalloc
(((
CPQFC_MAX_PASSTHRU_CMDS
+
BITS_PER_LONG
-
1
)
/
BITS_PER_LONG
)
*
sizeof
(
unsigned
long
),
GFP_KERNEL
);
if
(
hba
->
private_data_bits
==
NULL
)
return
-
1
;
memset
(
hba
->
private_data_bits
,
0
,
((
CPQFC_MAX_PASSTHRU_CMDS
+
BITS_PER_LONG
-
1
)
/
BITS_PER_LONG
)
*
sizeof
(
unsigned
long
));
hba
->
private_data_pool
=
kmalloc
(
sizeof
(
cpqfc_passthru_private_t
)
*
CPQFC_MAX_PASSTHRU_CMDS
,
GFP_KERNEL
);
if
(
hba
->
private_data_pool
==
NULL
)
{
kfree
(
hba
->
private_data_bits
);
hba
->
private_data_bits
=
NULL
;
return
-
1
;
}
return
0
;
}
static
void
cpqfc_free_private_data_pool
(
CPQFCHBA
*
hba
)
{
kfree
(
hba
->
private_data_bits
);
kfree
(
hba
->
private_data_pool
);
}
int
is_private_data_of_cpqfc
(
CPQFCHBA
*
hba
,
void
*
pointer
)
{
/* Is pointer within our private data pool?
We use Scsi_Request->upper_private_data (normally
reserved for upper layer drivers, e.g. the sg driver)
We check to see if the pointer is ours by looking at
its address. Is this ok? Hmm, it occurs to me that
a user app might do something bad by using sg to send
a cpqfc passthrough ioctl with upper_data_private
forged to be somewhere in our pool..., though they'd
normally have to be root already to do this. */
return
(
pointer
!=
NULL
&&
pointer
>=
(
void
*
)
hba
->
private_data_pool
&&
pointer
<
(
void
*
)
hba
->
private_data_pool
+
sizeof
(
*
hba
->
private_data_pool
)
*
CPQFC_MAX_PASSTHRU_CMDS
);
}
cpqfc_passthru_private_t
*
cpqfc_alloc_private_data
(
CPQFCHBA
*
hba
)
{
int
i
;
do
{
i
=
find_first_zero_bit
(
hba
->
private_data_bits
,
CPQFC_MAX_PASSTHRU_CMDS
);
if
(
i
==
CPQFC_MAX_PASSTHRU_CMDS
)
return
NULL
;
}
while
(
test_and_set_bit
(
i
&
(
BITS_PER_LONG
-
1
),
hba
->
private_data_bits
+
(
i
/
BITS_PER_LONG
))
!=
0
);
return
&
hba
->
private_data_pool
[
i
];
}
void
cpqfc_free_private_data
(
CPQFCHBA
*
hba
,
cpqfc_passthru_private_t
*
data
)
{
int
i
;
i
=
data
-
hba
->
private_data_pool
;
clear_bit
(
i
&
(
BITS_PER_LONG
-
1
),
hba
->
private_data_bits
+
(
i
/
BITS_PER_LONG
));
}
int
cpqfcTS_ioctl
(
Scsi_Device
*
ScsiDev
,
int
Cmnd
,
void
*
arg
)
int
cpqfcTS_ioctl
(
Scsi_Device
*
ScsiDev
,
int
Cmnd
,
void
*
arg
)
{
{
...
@@ -490,35 +563,19 @@ int cpqfcTS_ioctl( Scsi_Device *ScsiDev, int Cmnd, void *arg)
...
@@ -490,35 +563,19 @@ int cpqfcTS_ioctl( Scsi_Device *ScsiDev, int Cmnd, void *arg)
struct
Scsi_Host
*
HostAdapter
=
ScsiDev
->
host
;
struct
Scsi_Host
*
HostAdapter
=
ScsiDev
->
host
;
CPQFCHBA
*
cpqfcHBAdata
=
(
CPQFCHBA
*
)
HostAdapter
->
hostdata
;
CPQFCHBA
*
cpqfcHBAdata
=
(
CPQFCHBA
*
)
HostAdapter
->
hostdata
;
PTACHYON
fcChip
=
&
cpqfcHBAdata
->
fcChip
;
PTACHYON
fcChip
=
&
cpqfcHBAdata
->
fcChip
;
PFC_LOGGEDIN_PORT
pLoggedInPort
;
PFC_LOGGEDIN_PORT
pLoggedInPort
=
NULL
;
Scsi_Cmnd
DumCmnd
;
Scsi_Cmnd
DumCmnd
;
int
i
,
j
;
int
i
,
j
;
VENDOR_IOCTL_REQ
ioc
;
VENDOR_IOCTL_REQ
ioc
;
cpqfc_passthru_t
*
vendor_cmd
;
cpqfc_passthru_t
*
vendor_cmd
;
Scsi_Device
*
SDpnt
;
Scsi_Device
*
SDpnt
;
Scsi_Cmnd
*
ScsiPassThruCmnd
;
Scsi_Request
*
ScsiPassThruReq
;
cpqfc_passthru_private_t
*
privatedata
;
ENTER
(
"cpqfcTS_ioctl "
);
ENTER
(
"cpqfcTS_ioctl "
);
// can we find an FC device mapping to this SCSI target?
// printk("ioctl CMND %d", Cmnd);
DumCmnd
.
channel
=
ScsiDev
->
channel
;
// For searching
switch
(
Cmnd
)
{
DumCmnd
.
target
=
ScsiDev
->
id
;
pLoggedInPort
=
fcFindLoggedInPort
(
fcChip
,
&
DumCmnd
,
// search Scsi Nexus
0
,
// DON'T search linked list for FC port id
NULL
,
// DON'T search linked list for FC WWN
NULL
);
// DON'T care about end of list
if
(
pLoggedInPort
==
NULL
)
// not found!
{
result
=
-
ENXIO
;
}
else
// we know what FC device to operate on...
{
// printk("ioctl CMND %d", Cmnd);
switch
(
Cmnd
)
{
// Passthrough provides a mechanism to bypass the RAID
// Passthrough provides a mechanism to bypass the RAID
// or other controller and talk directly to the devices
// or other controller and talk directly to the devices
// (e.g. physical disk drive)
// (e.g. physical disk drive)
...
@@ -527,6 +584,10 @@ int cpqfcTS_ioctl( Scsi_Device *ScsiDev, int Cmnd, void *arg)
...
@@ -527,6 +584,10 @@ int cpqfcTS_ioctl( Scsi_Device *ScsiDev, int Cmnd, void *arg)
case
CPQFCTS_SCSI_PASSTHRU
:
case
CPQFCTS_SCSI_PASSTHRU
:
{
{
void
*
buf
=
NULL
;
// for kernel space buffer for user data
void
*
buf
=
NULL
;
// for kernel space buffer for user data
/* Check that our pool got allocated ok. */
if
(
cpqfcHBAdata
->
private_data_pool
==
NULL
)
return
-
ENOMEM
;
if
(
!
arg
)
if
(
!
arg
)
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -549,83 +610,70 @@ int cpqfcTS_ioctl( Scsi_Device *ScsiDev, int Cmnd, void *arg)
...
@@ -549,83 +610,70 @@ int cpqfcTS_ioctl( Scsi_Device *ScsiDev, int Cmnd, void *arg)
if
(
!
buf
)
if
(
!
buf
)
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
// Now build a Scsi_Request to pass down...
ScsiPassThruReq
=
scsi_allocate_request
(
ScsiDev
);
if
(
ScsiPassThruReq
==
NULL
)
{
kfree
(
buf
);
return
-
ENOMEM
;
}
ScsiPassThruReq
->
upper_private_data
=
cpqfc_alloc_private_data
(
cpqfcHBAdata
);
if
(
ScsiPassThruReq
->
upper_private_data
==
NULL
)
{
kfree
(
buf
);
scsi_release_request
(
ScsiPassThruReq
);
// "de-allocate"
return
-
ENOMEM
;
}
// Now build a SCSI_CMND to pass down...
if
(
vendor_cmd
->
rw_flag
==
VENDOR_WRITE_OPCODE
)
{
// This function allocates and sets Scsi_Cmnd ptrs such as
if
(
vendor_cmd
->
len
)
{
// Need data from user?
// ->channel, ->target, ->host
if
(
copy_from_user
(
buf
,
vendor_cmd
->
bufp
,
ScsiPassThruCmnd
=
scsi_allocate_device
(
ScsiDev
,
1
,
1
);
vendor_cmd
->
len
))
{
kfree
(
buf
);
// Need data from user?
cpqfc_free_private_data
(
cpqfcHBAdata
,
// make sure caller's buffer is in kernel space.
ScsiPassThruReq
->
upper_private_data
);
if
(
(
vendor_cmd
->
rw_flag
==
VENDOR_WRITE_OPCODE
)
&&
scsi_release_request
(
ScsiPassThruReq
);
vendor_cmd
->
len
)
return
(
-
EFAULT
);
if
(
copy_from_user
(
buf
,
vendor_cmd
->
bufp
,
vendor_cmd
->
len
))
}
return
(
-
EFAULT
);
}
ScsiPassThruReq
->
sr_data_direction
=
SCSI_DATA_WRITE
;
}
else
if
(
vendor_cmd
->
rw_flag
==
VENDOR_READ_OPCODE
)
{
ScsiPassThruReq
->
sr_data_direction
=
SCSI_DATA_READ
;
}
else
// maybe this means a bug in the user app
ScsiPassThruReq
->
sr_data_direction
=
SCSI_DATA_NONE
;
// copy the CDB (if/when MAX_COMMAND_SIZE is 16, remove copy below)
ScsiPassThruReq
->
sr_cmd_len
=
0
;
// set correctly by scsi_do_req()
memcpy
(
&
ScsiPassThruCmnd
->
cmnd
[
0
],
ScsiPassThruReq
->
sr_sense_buffer
[
0
]
=
0
;
&
vendor_cmd
->
cdb
[
0
],
ScsiPassThruReq
->
sr_sense_buffer
[
2
]
=
0
;
MAX_COMMAND_SIZE
);
// we want to copy all 16 bytes into the FCP-SCSI CDB,
// although the actual passthru only uses up to the
// first 12.
ScsiPassThruCmnd
->
cmd_len
=
16
;
// sizeof FCP-SCSI CDB
// Unfortunately, the SCSI command cmnd[] field has only
// 12 bytes. Ideally the MAX_COMMAND_SIZE should be increased
// to 16 for newer Fibre Channel and SCSI-3 larger CDBs.
// However, to avoid a mandatory kernel rebuild, we use the SCp
// spare field to store the extra 4 bytes ( ugly :-(
if
(
MAX_COMMAND_SIZE
<
16
)
// We copy the scheme used by sd.c:spinup_disk() to submit commands
{
memcpy
(
&
ScsiPassThruCmnd
->
SCp
.
buffers_residual
,
&
vendor_cmd
->
cdb
[
12
],
4
);
}
ScsiPassThruCmnd
->
SCp
.
sent_command
=
1
;
// PASSTHRU!
// suppress LUN masking
// and VSA logic
// Use spare fields to copy FCP-SCSI LUN address info...
ScsiPassThruCmnd
->
SCp
.
phase
=
vendor_cmd
->
bus
;
ScsiPassThruCmnd
->
SCp
.
have_data_in
=
vendor_cmd
->
pdrive
;
// We copy the scheme used by scsi.c to submit commands
// to our own HBA. We do this in order to stall the
// to our own HBA. We do this in order to stall the
// thread calling the IOCTL until it completes, and use
// thread calling the IOCTL until it completes, and use
// the same "_quecommand" function for synchronizing
// the same "_quecommand" function for synchronizing
// FC Link events with our "worker thread".
// FC Link events with our "worker thread".
{
privatedata
=
ScsiPassThruReq
->
upper_private_data
;
CPQFC_DECLARE_COMPLETION
(
wait
);
privatedata
->
bus
=
vendor_cmd
->
bus
;
ScsiPassThruCmnd
->
request
->
CPQFC_WAITING
=
&
wait
;
privatedata
->
pdrive
=
vendor_cmd
->
pdrive
;
// eventually gets us to our own _quecommand routine
scsi_do_cmd
(
ScsiPassThruCmnd
,
&
vendor_cmd
->
cdb
[
0
],
buf
,
vendor_cmd
->
len
,
my_ioctl_done
,
10
*
HZ
,
1
);
// timeout,retries
// Other I/Os can now resume; we wait for our ioctl
// command to complete
CPQFC_WAIT_FOR_COMPLETION
(
&
wait
);
ScsiPassThruCmnd
->
request
->
CPQFC_WAITING
=
NULL
;
}
result
=
ScsiPassThruCmnd
->
result
;
// eventually gets us to our own _quecommand routine
scsi_wait_req
(
ScsiPassThruReq
,
&
vendor_cmd
->
cdb
[
0
],
buf
,
vendor_cmd
->
len
,
10
*
HZ
,
// timeout
1
);
// retries
result
=
ScsiPassThruReq
->
sr_result
;
// copy any sense data back to caller
// copy any sense data back to caller
if
(
result
!=
0
)
if
(
result
!=
0
)
{
{
memcpy
(
vendor_cmd
->
sense_data
,
// see struct def - size=40
memcpy
(
vendor_cmd
->
sense_data
,
// see struct def - size=40
ScsiPassThru
Cmnd
->
sense_buffer
,
ScsiPassThru
Req
->
sr_
sense_buffer
,
sizeof
(
ScsiPassThru
Cmnd
->
sense_buffer
));
sizeof
(
ScsiPassThru
Req
->
sr_
sense_buffer
));
}
}
SDpnt
=
ScsiPassThruCmnd
->
device
;
SDpnt
=
ScsiPassThruReq
->
sr_device
;
scsi_release_command
(
ScsiPassThruCmnd
);
// "de-allocate"
/* upper_private_data is already freed in call_scsi_done() */
ScsiPassThruCmnd
=
NULL
;
scsi_release_request
(
ScsiPassThruReq
);
// "de-allocate"
ScsiPassThruReq
=
NULL
;
// if (!SDpnt->was_reset && SDpnt->scsi_request_fn)
// if (!SDpnt->was_reset && SDpnt->scsi_request_fn)
// (*SDpnt->scsi_request_fn)();
// (*SDpnt->scsi_request_fn)();
...
@@ -679,10 +727,21 @@ int cpqfcTS_ioctl( Scsi_Device *ScsiDev, int Cmnd, void *arg)
...
@@ -679,10 +727,21 @@ int cpqfcTS_ioctl( Scsi_Device *ScsiDev, int Cmnd, void *arg)
case
CPQFC_IOCTL_FC_TARGET_ADDRESS
:
case
CPQFC_IOCTL_FC_TARGET_ADDRESS
:
result
=
// can we find an FC device mapping to this SCSI target?
verify_area
(
VERIFY_WRITE
,
arg
,
sizeof
(
Scsi_FCTargAddress
));
DumCmnd
.
channel
=
ScsiDev
->
channel
;
// For searching
if
(
result
)
DumCmnd
.
target
=
ScsiDev
->
id
;
break
;
DumCmnd
.
lun
=
ScsiDev
->
lun
;
pLoggedInPort
=
fcFindLoggedInPort
(
fcChip
,
&
DumCmnd
,
// search Scsi Nexus
0
,
// DON'T search linked list for FC port id
NULL
,
// DON'T search linked list for FC WWN
NULL
);
// DON'T care about end of list
if
(
pLoggedInPort
==
NULL
)
{
result
=
-
ENXIO
;
break
;
}
result
=
verify_area
(
VERIFY_WRITE
,
arg
,
sizeof
(
Scsi_FCTargAddress
));
if
(
result
)
break
;
put_user
(
pLoggedInPort
->
port_id
,
put_user
(
pLoggedInPort
->
port_id
,
&
((
Scsi_FCTargAddress
*
)
arg
)
->
host_port_id
);
&
((
Scsi_FCTargAddress
*
)
arg
)
->
host_port_id
);
...
@@ -709,7 +768,6 @@ int cpqfcTS_ioctl( Scsi_Device *ScsiDev, int Cmnd, void *arg)
...
@@ -709,7 +768,6 @@ int cpqfcTS_ioctl( Scsi_Device *ScsiDev, int Cmnd, void *arg)
result
=
-
EINVAL
;
result
=
-
EINVAL
;
break
;
break
;
}
}
}
LEAVE
(
"cpqfcTS_ioctl"
);
LEAVE
(
"cpqfcTS_ioctl"
);
return
result
;
return
result
;
...
@@ -747,6 +805,7 @@ int cpqfcTS_release(struct Scsi_Host *HostAdapter)
...
@@ -747,6 +805,7 @@ int cpqfcTS_release(struct Scsi_Host *HostAdapter)
}
}
cpqfc_free_private_data_pool
(
cpqfcHBAdata
);
// free Linux resources
// free Linux resources
DEBUG_PCI
(
printk
(
" cpqfcTS: freeing resources...
\n
"
));
DEBUG_PCI
(
printk
(
" cpqfcTS: freeing resources...
\n
"
));
free_irq
(
HostAdapter
->
irq
,
HostAdapter
);
free_irq
(
HostAdapter
->
irq
,
HostAdapter
);
...
@@ -1527,6 +1586,12 @@ int cpqfcTS_TargetDeviceReset( Scsi_Device *ScsiDev,
...
@@ -1527,6 +1586,12 @@ int cpqfcTS_TargetDeviceReset( Scsi_Device *ScsiDev,
Scsi_Cmnd
*
SCpnt
;
Scsi_Cmnd
*
SCpnt
;
Scsi_Device
*
SDpnt
;
Scsi_Device
*
SDpnt
;
// FIXME, cpqfcTS_TargetDeviceReset needs to be fixed
// similarly to how the passthrough ioctl was fixed
// around the 2.5.30 kernel. Scsi_Cmnd replaced with
// Scsi_Request, etc.
// For now, so people don't fall into a hole...
return
-
ENOTSUPP
;
// printk(" ENTERING cpqfcTS_TargetDeviceReset() - flag=%d \n",reset_flags);
// printk(" ENTERING cpqfcTS_TargetDeviceReset() - flag=%d \n",reset_flags);
...
@@ -1540,9 +1605,10 @@ int cpqfcTS_TargetDeviceReset( Scsi_Device *ScsiDev,
...
@@ -1540,9 +1605,10 @@ int cpqfcTS_TargetDeviceReset( Scsi_Device *ScsiDev,
SCpnt
=
scsi_allocate_device
(
ScsiDev
,
1
,
0
);
SCpnt
=
scsi_allocate_device
(
ScsiDev
,
1
,
0
);
{
{
CPQFC_DECLARE_COMPLETION
(
wait
);
CPQFC_DECLARE_COMPLETION
(
wait
);
SCpnt
->
SCp
.
buffers_residual
=
FCP_TARGET_RESET
;
SCpnt
->
SCp
.
buffers_residual
=
FCP_TARGET_RESET
;
// FIXME: this would panic, SCpnt->request would be NULL.
SCpnt
->
request
->
CPQFC_WAITING
=
&
wait
;
SCpnt
->
request
->
CPQFC_WAITING
=
&
wait
;
scsi_do_cmd
(
SCpnt
,
scsi_cdb
,
NULL
,
0
,
my_ioctl_done
,
timeout
,
retries
);
scsi_do_cmd
(
SCpnt
,
scsi_cdb
,
NULL
,
0
,
my_ioctl_done
,
timeout
,
retries
);
CPQFC_WAIT_FOR_COMPLETION
(
&
wait
);
CPQFC_WAIT_FOR_COMPLETION
(
&
wait
);
...
@@ -1701,6 +1767,18 @@ void cpqfcTS_intr_handler( int irq,
...
@@ -1701,6 +1767,18 @@ void cpqfcTS_intr_handler( int irq,
UCHAR
IntStat
;
UCHAR
IntStat
;
printk
(
" cpqfcTS adapter PCI error detected
\n
"
);
printk
(
" cpqfcTS adapter PCI error detected
\n
"
);
IntStat
=
readb
(
cpqfcHBA
->
fcChip
.
Registers
.
INTSTAT
.
address
);
IntStat
=
readb
(
cpqfcHBA
->
fcChip
.
Registers
.
INTSTAT
.
address
);
printk
(
"cpqfc: ISR = 0x%02x
\n
"
,
IntStat
);
if
(
IntStat
&
0x1
)
{
__u16
pcistat
;
/* read the pci status register */
pci_read_config_word
(
cpqfcHBA
->
PciDev
,
0x06
,
&
pcistat
);
printk
(
"PCI status register is 0x%04x
\n
"
,
pcistat
);
if
(
pcistat
&
0x8000
)
printk
(
"Parity Error Detected.
\n
"
);
if
(
pcistat
&
0x4000
)
printk
(
"Signalled System Error
\n
"
);
if
(
pcistat
&
0x2000
)
printk
(
"Received Master Abort
\n
"
);
if
(
pcistat
&
0x1000
)
printk
(
"Received Target Abort
\n
"
);
if
(
pcistat
&
0x0800
)
printk
(
"Signalled Target Abort
\n
"
);
}
if
(
IntStat
&
0x4
)
printk
(
"(INT)
\n
"
);
if
(
IntStat
&
0x4
)
printk
(
"(INT)
\n
"
);
if
(
IntStat
&
0x8
)
if
(
IntStat
&
0x8
)
printk
(
"CRS: PCI master address crossed 46 bit bouandary
\n
"
);
printk
(
"CRS: PCI master address crossed 46 bit bouandary
\n
"
);
...
...
drivers/scsi/cpqfcTSstructs.h
View file @
12c262b2
...
@@ -33,7 +33,7 @@
...
@@ -33,7 +33,7 @@
// don't forget to also change MODULE_DESCRIPTION in cpqfcTSinit.c
// don't forget to also change MODULE_DESCRIPTION in cpqfcTSinit.c
#define VER_MAJOR 2
#define VER_MAJOR 2
#define VER_MINOR 5
#define VER_MINOR 5
#define VER_SUBMINOR
0
#define VER_SUBMINOR
3
// Macros for kernel (esp. SMP) tracing using a PCI analyzer
// Macros for kernel (esp. SMP) tracing using a PCI analyzer
// (e.g. x86).
// (e.g. x86).
...
@@ -907,9 +907,17 @@ typedef struct
...
@@ -907,9 +907,17 @@ typedef struct
}
FC_SCSI_QUE
,
*
PFC_SCSI_QUE
;
}
FC_SCSI_QUE
,
*
PFC_SCSI_QUE
;
typedef
struct
{
/* This is tacked on to a Scsi_Request in upper_private_data
for pasthrough ioctls, as a place to hold data that can't
be stashed anywhere else in the Scsi_Request. We differentiate
this from _real_ upper_private_data by checking if the virt addr
is within our special pool. */
ushort
bus
;
ushort
pdrive
;
}
cpqfc_passthru_private_t
;
#define CPQFC_MAX_PASSTHRU_CMDS 100
#define DYNAMIC_ALLOCATIONS 4 // Tachyon aligned allocations: ERQ,IMQ,SFQ,SEST
#define DYNAMIC_ALLOCATIONS 4 // Tachyon aligned allocations: ERQ,IMQ,SFQ,SEST
...
@@ -949,6 +957,8 @@ typedef struct
...
@@ -949,6 +957,8 @@ typedef struct
PFC_LINK_QUE
fcLQ
;
// the WorkerThread operates on this
PFC_LINK_QUE
fcLQ
;
// the WorkerThread operates on this
spinlock_t
hba_spinlock
;
// held/released by WorkerThread
spinlock_t
hba_spinlock
;
// held/released by WorkerThread
cpqfc_passthru_private_t
*
private_data_pool
;
unsigned
long
*
private_data_bits
;
}
CPQFCHBA
;
}
CPQFCHBA
;
...
@@ -1405,6 +1415,7 @@ struct ext_sg_entry_t {
...
@@ -1405,6 +1415,7 @@ struct ext_sg_entry_t {
__u32
lba
;
/* lower bus address bits 0-31 */
__u32
lba
;
/* lower bus address bits 0-31 */
};
};
// J. McCarty's LINK.H
// J. McCarty's LINK.H
//
//
// LS_RJT Reason Codes
// LS_RJT Reason Codes
...
...
drivers/scsi/cpqfcTSworker.c
View file @
12c262b2
...
@@ -2887,15 +2887,22 @@ static void ScsiReportLunsDone(Scsi_Cmnd *Cmnd)
...
@@ -2887,15 +2887,22 @@ static void ScsiReportLunsDone(Scsi_Cmnd *Cmnd)
Done:
Done:
}
}
extern
int
is_private_data_of_cpqfc
(
CPQFCHBA
*
hba
,
void
*
pointer
);
extern
void
cpqfc_free_private_data
(
CPQFCHBA
*
hba
,
cpqfc_passthru_private_t
*
data
);
static
void
static
void
call_scsi_done
(
Scsi_Cmnd
*
Cmnd
)
call_scsi_done
(
Scsi_Cmnd
*
Cmnd
)
{
{
// We have to reinitialize sent_command here, so the scsi-mid
CPQFCHBA
*
hba
;
// layer won't re-use the scsi command leaving it set incorrectly.
hba
=
(
CPQFCHBA
*
)
Cmnd
->
host
->
hostdata
;
// (incorrectly for our purposes...it's normally unused.)
// Was this command a cpqfc passthru ioctl ?
if
(
Cmnd
->
sc_request
!=
NULL
&&
Cmnd
->
host
!=
NULL
&&
if
(
Cmnd
->
SCp
.
sent_command
!=
0
)
{
// was it a passthru?
Cmnd
->
host
->
hostdata
!=
NULL
&&
Cmnd
->
SCp
.
sent_command
=
0
;
is_private_data_of_cpqfc
((
CPQFCHBA
*
)
Cmnd
->
host
->
hostdata
,
Cmnd
->
sc_request
->
upper_private_data
))
{
cpqfc_free_private_data
(
hba
,
Cmnd
->
sc_request
->
upper_private_data
);
Cmnd
->
sc_request
->
upper_private_data
=
NULL
;
Cmnd
->
result
&=
0xff00ffff
;
Cmnd
->
result
&=
0xff00ffff
;
Cmnd
->
result
|=
(
DID_PASSTHROUGH
<<
16
);
// prevents retry
Cmnd
->
result
|=
(
DID_PASSTHROUGH
<<
16
);
// prevents retry
}
}
...
@@ -3293,6 +3300,7 @@ static int GetLoopID( ULONG al_pa )
...
@@ -3293,6 +3300,7 @@ static int GetLoopID( ULONG al_pa )
}
}
#endif
#endif
extern
cpqfc_passthru_private_t
*
cpqfc_private
(
Scsi_Request
*
sr
);
// Search the singly (forward) linked list "fcPorts" looking for
// Search the singly (forward) linked list "fcPorts" looking for
// either the SCSI target (if != -1), port_id (if not NULL),
// either the SCSI target (if != -1), port_id (if not NULL),
...
@@ -3366,8 +3374,18 @@ PFC_LOGGEDIN_PORT fcFindLoggedInPort(
...
@@ -3366,8 +3374,18 @@ PFC_LOGGEDIN_PORT fcFindLoggedInPort(
{
{
// For "passthru" modes, the IOCTL caller is responsible
// For "passthru" modes, the IOCTL caller is responsible
// for setting the FCP-LUN addressing
// for setting the FCP-LUN addressing
if
(
!
Cmnd
->
SCp
.
sent_command
)
// NOT passthru?
if
(
Cmnd
->
sc_request
!=
NULL
&&
Cmnd
->
host
!=
NULL
&&
{
Cmnd
->
host
->
hostdata
!=
NULL
&&
is_private_data_of_cpqfc
((
CPQFCHBA
*
)
Cmnd
->
host
->
hostdata
,
Cmnd
->
sc_request
->
upper_private_data
))
{
/* This is a passthru... */
cpqfc_passthru_private_t
*
pd
;
pd
=
Cmnd
->
sc_request
->
upper_private_data
;
Cmnd
->
SCp
.
phase
=
pd
->
bus
;
// Cmnd->SCp.have_data_in = pd->pdrive;
Cmnd
->
SCp
.
have_data_in
=
Cmnd
->
lun
;
}
else
{
/* This is not a passthru... */
// set the FCP-LUN addressing type
// set the FCP-LUN addressing type
Cmnd
->
SCp
.
phase
=
pLoggedInPort
->
ScsiNexus
.
VolumeSetAddressing
;
Cmnd
->
SCp
.
phase
=
pLoggedInPort
->
ScsiNexus
.
VolumeSetAddressing
;
...
@@ -3380,6 +3398,8 @@ PFC_LOGGEDIN_PORT fcFindLoggedInPort(
...
@@ -3380,6 +3398,8 @@ PFC_LOGGEDIN_PORT fcFindLoggedInPort(
// Report Luns command
// Report Luns command
if
(
pLoggedInPort
->
ScsiNexus
.
LunMasking
==
1
)
if
(
pLoggedInPort
->
ScsiNexus
.
LunMasking
==
1
)
{
{
if
(
Cmnd
->
lun
>
sizeof
(
pLoggedInPort
->
ScsiNexus
.
lun
))
return
NULL
;
// we KNOW all the valid LUNs... 0xFF is invalid!
// we KNOW all the valid LUNs... 0xFF is invalid!
Cmnd
->
SCp
.
have_data_in
=
pLoggedInPort
->
ScsiNexus
.
lun
[
Cmnd
->
lun
];
Cmnd
->
SCp
.
have_data_in
=
pLoggedInPort
->
ScsiNexus
.
lun
[
Cmnd
->
lun
];
if
(
pLoggedInPort
->
ScsiNexus
.
lun
[
Cmnd
->
lun
]
==
0xFF
)
if
(
pLoggedInPort
->
ScsiNexus
.
lun
[
Cmnd
->
lun
]
==
0xFF
)
...
@@ -3504,7 +3524,6 @@ static void UnblockScsiDevice( struct Scsi_Host *HostAdapter,
...
@@ -3504,7 +3524,6 @@ static void UnblockScsiDevice( struct Scsi_Host *HostAdapter,
{
{
printk
(
"LinkDnCmnd scsi_done ptr null, port_id %Xh
\n
"
,
printk
(
"LinkDnCmnd scsi_done ptr null, port_id %Xh
\n
"
,
pLoggedInPort
->
port_id
);
pLoggedInPort
->
port_id
);
Cmnd
->
SCp
.
sent_command
=
0
;
}
}
else
else
call_scsi_done
(
Cmnd
);
call_scsi_done
(
Cmnd
);
...
@@ -5232,7 +5251,6 @@ static ULONG build_SEST_sgList(
...
@@ -5232,7 +5251,6 @@ static ULONG build_SEST_sgList(
sgl
=
(
struct
scatterlist
*
)
Cmnd
->
request_buffer
;
sgl
=
(
struct
scatterlist
*
)
Cmnd
->
request_buffer
;
sg_count
=
pci_map_sg
(
pcidev
,
sgl
,
Cmnd
->
use_sg
,
sg_count
=
pci_map_sg
(
pcidev
,
sgl
,
Cmnd
->
use_sg
,
scsi_to_pci_dma_dir
(
Cmnd
->
sc_data_direction
));
scsi_to_pci_dma_dir
(
Cmnd
->
sc_data_direction
));
// printk("sgl = %p, sg_count = %d\n", (void *) sgl, sg_count);
if
(
sg_count
<=
3
)
{
if
(
sg_count
<=
3
)
{
// we need to be careful here that no individual mapping
// we need to be careful here that no individual mapping
...
@@ -5261,7 +5279,6 @@ static ULONG build_SEST_sgList(
...
@@ -5261,7 +5279,6 @@ static ULONG build_SEST_sgList(
// printk("totalsgs = %d, sgcount=%d\n",totalsgs,sg_count);
// printk("totalsgs = %d, sgcount=%d\n",totalsgs,sg_count);
}
}
// printk("totalsgs = %d, sgcount=%d\n", totalsgs, sg_count);
if
(
totalsgs
<=
3
)
// can (must) use "local" SEST list
if
(
totalsgs
<=
3
)
// can (must) use "local" SEST list
{
{
while
(
bytes_to_go
)
while
(
bytes_to_go
)
...
@@ -6164,13 +6181,11 @@ void cpqfcTSCompleteExchange(
...
@@ -6164,13 +6181,11 @@ void cpqfcTSCompleteExchange(
}
}
else
else
{
{
Exchanges
->
fcExchange
[
x_ID
].
Cmnd
->
SCp
.
sent_command
=
0
;
// printk(" not calling scsi_done on x_ID %Xh, Cmnd %p\n",
// printk(" not calling scsi_done on x_ID %Xh, Cmnd %p\n",
// x_ID, Exchanges->fcExchange[ x_ID ].Cmnd);
// x_ID, Exchanges->fcExchange[ x_ID ].Cmnd);
}
}
}
}
else
{
else
{
Exchanges
->
fcExchange
[
x_ID
].
Cmnd
->
SCp
.
sent_command
=
0
;
printk
(
" x_ID %Xh, type %Xh, Cdb0 %Xh
\n
"
,
x_ID
,
printk
(
" x_ID %Xh, type %Xh, Cdb0 %Xh
\n
"
,
x_ID
,
Exchanges
->
fcExchange
[
x_ID
].
type
,
Exchanges
->
fcExchange
[
x_ID
].
type
,
Exchanges
->
fcExchange
[
x_ID
].
Cmnd
->
cmnd
[
0
]);
Exchanges
->
fcExchange
[
x_ID
].
Cmnd
->
cmnd
[
0
]);
...
@@ -6463,10 +6478,10 @@ static int build_FCP_payload( Scsi_Cmnd *Cmnd,
...
@@ -6463,10 +6478,10 @@ static int build_FCP_payload( Scsi_Cmnd *Cmnd,
for
(
i
=
0
;
(
i
<
Cmnd
->
cmd_len
)
&&
i
<
MAX_COMMAND_SIZE
;
i
++
)
for
(
i
=
0
;
(
i
<
Cmnd
->
cmd_len
)
&&
i
<
MAX_COMMAND_SIZE
;
i
++
)
*
payload
++
=
Cmnd
->
cmnd
[
i
];
*
payload
++
=
Cmnd
->
cmnd
[
i
];
if
(
Cmnd
->
cmd_len
==
16
)
//
if( Cmnd->cmd_len == 16 )
{
//
{
memcpy
(
payload
,
&
Cmnd
->
SCp
.
buffers_residual
,
4
);
//
memcpy( payload, &Cmnd->SCp.buffers_residual, 4);
}
//
}
payload
+=
(
16
-
i
);
payload
+=
(
16
-
i
);
// FCP_DL is largest number of expected data bytes
// FCP_DL is largest number of expected data bytes
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment