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
Kirill Smelkov
linux
Commits
49ce412f
Commit
49ce412f
authored
Nov 06, 2002
by
James Bottomley
Browse files
Options
Browse Files
Download
Plain Diff
Merge dougg/cloos changes in sbp2.h
parents
32e71bf0
f4e01df0
Changes
20
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
686 additions
and
819 deletions
+686
-819
drivers/ieee1394/sbp2.c
drivers/ieee1394/sbp2.c
+1
-1
drivers/ieee1394/sbp2.h
drivers/ieee1394/sbp2.h
+2
-1
drivers/scsi/Kconfig
drivers/scsi/Kconfig
+0
-17
drivers/scsi/hosts.c
drivers/scsi/hosts.c
+78
-116
drivers/scsi/hosts.h
drivers/scsi/hosts.h
+17
-42
drivers/scsi/megaraid.c
drivers/scsi/megaraid.c
+6
-187
drivers/scsi/megaraid.h
drivers/scsi/megaraid.h
+0
-4
drivers/scsi/osst.c
drivers/scsi/osst.c
+30
-22
drivers/scsi/scsi.c
drivers/scsi/scsi.c
+120
-53
drivers/scsi/scsi.h
drivers/scsi/scsi.h
+5
-0
drivers/scsi/scsi_debug.c
drivers/scsi/scsi_debug.c
+218
-70
drivers/scsi/scsi_debug.h
drivers/scsi/scsi_debug.h
+13
-8
drivers/scsi/scsi_mid_low_api.txt
drivers/scsi/scsi_mid_low_api.txt
+1
-23
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_scan.c
+2
-32
drivers/scsi/scsi_syms.c
drivers/scsi/scsi_syms.c
+4
-1
drivers/scsi/sd.c
drivers/scsi/sd.c
+10
-8
drivers/scsi/sg.c
drivers/scsi/sg.c
+38
-72
drivers/scsi/sr.c
drivers/scsi/sr.c
+118
-143
drivers/scsi/sr.h
drivers/scsi/sr.h
+1
-0
drivers/scsi/st.c
drivers/scsi/st.c
+22
-19
No files found.
drivers/ieee1394/sbp2.c
View file @
49ce412f
...
...
@@ -3137,7 +3137,7 @@ static int sbp2scsi_reset (Scsi_Cmnd *SCpnt)
/*
* Called by scsi stack to get bios parameters (used by fdisk, and at boot).
*/
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,4
4
)
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,4
3
)
static
int
sbp2scsi_biosparam
(
struct
scsi_device
*
sdev
,
struct
block_device
*
dev
,
sector_t
capacity
,
int
geom
[])
{
...
...
drivers/ieee1394/sbp2.h
View file @
49ce412f
...
...
@@ -552,7 +552,8 @@ void sbp2scsi_setup(char *str, int *ints);
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,44)
static
int
sbp2scsi_biosparam
(
struct
scsi_device
*
sdev
,
struct
block_device
*
dev
,
sector_t
capacity
,
int
geom
[]);
#else
static
int
sbp2scsi_biosparam
(
Scsi_Disk
*
disk
,
kdev_t
dev
,
int
geom
[]);
static
int
sbp2scsi_biosparam
(
struct
scsi_device
*
sdev
,
struct
block_device
*
dev
,
sector_t
capacy
,
int
geom
[]);
#endif
static
int
sbp2scsi_abort
(
Scsi_Cmnd
*
SCpnt
);
static
int
sbp2scsi_reset
(
Scsi_Cmnd
*
SCpnt
);
...
...
drivers/scsi/Kconfig
View file @
49ce412f
...
...
@@ -85,23 +85,6 @@ config BLK_DEV_SR_VENDOR
drives
(
and
HP
Writers
).
If
you
have
such
a
drive
and
get
the
first
session
only
,
try
saying
Y
here
;
everybody
else
says
N
.
config
SR_EXTRA_DEVS
int
"Maximum number of CDROM devices that can be loaded as modules"
depends
on
BLK_DEV_SR
default
"2"
---
help
---
This
controls
the
amount
of
additional
space
allocated
in
tables
for
drivers
that
are
loaded
as
modules
after
the
kernel
is
booted
.
In
the
event
that
the
SCSI
core
itself
was
loaded
as
a
module
,
this
value
is
the
number
of
additional
CD
-
ROMs
that
can
be
loaded
after
the
first
host
driver
is
loaded
.
Admittedly
this
isn
't pretty, but there are tons of race conditions
involved with resizing the internal arrays on the fly. Someday this
flag will go away, and everything will work automatically.
If you don'
t
understand
what
's going on, go with the default.
config
CHR_DEV_SG
tristate
"SCSI generic support"
depends
on
SCSI
...
...
drivers/scsi/hosts.c
View file @
49ce412f
...
...
@@ -45,13 +45,9 @@
#include "scsi.h"
#include "hosts.h"
LIST_HEAD
(
scsi_host_tmpl_list
);
LIST_HEAD
(
scsi_host_hn_list
);
LIST_HEAD
(
scsi_host_list
);
spinlock_t
scsi_host_list_lock
=
SPIN_LOCK_UNLOCKED
;
struct
Scsi_Device_Template
*
scsi_devicelist
;
static
LIST_HEAD
(
scsi_host_hn_list
);
static
LIST_HEAD
(
scsi_host_list
);
static
spinlock_t
scsi_host_list_lock
=
SPIN_LOCK_UNLOCKED
;
static
int
scsi_host_next_hn
;
/* host_no for next new host */
static
int
scsi_hosts_registered
;
/* cnt of registered scsi hosts */
...
...
@@ -94,7 +90,7 @@ int scsi_tp_for_each_host(Scsi_Host_Template *shost_tp, int
* This is the default case for the release function. Its completely
* useless for anything but old ISA adapters
**/
static
void
scsi_host_
generic
_release
(
struct
Scsi_Host
*
shost
)
static
void
scsi_host_
legacy
_release
(
struct
Scsi_Host
*
shost
)
{
if
(
shost
->
irq
)
free_irq
(
shost
->
irq
,
NULL
);
...
...
@@ -104,19 +100,35 @@ static void scsi_host_generic_release(struct Scsi_Host *shost)
release_region
(
shost
->
io_port
,
shost
->
n_io_port
);
}
static
int
scsi_remove_legacy_host
(
struct
Scsi_Host
*
shost
)
{
int
error
,
pcount
=
scsi_hosts_registered
;
error
=
scsi_remove_host
(
shost
);
if
(
error
)
return
error
;
if
(
shost
->
hostt
->
release
)
(
*
shost
->
hostt
->
release
)(
shost
);
else
scsi_host_legacy_release
(
shost
);
if
(
pcount
==
scsi_hosts_registered
)
scsi_unregister
(
shost
);
return
0
;
}
/**
* scsi_
host_chk_and_release
- check a scsi host for release and release
* scsi_
remove_host
- check a scsi host for release and release
* @shost: a pointer to a scsi host to release
*
* Return value:
* 0 on Success / 1 on Failure
**/
int
scsi_
host_chk_and_release
(
struct
Scsi_Host
*
shost
)
int
scsi_
remove_host
(
struct
Scsi_Host
*
shost
)
{
int
pcount
;
Scsi_Device
*
sdev
;
struct
Scsi_Device_Template
*
sdev_tp
;
Scsi_Cmnd
*
scmd
;
struct
scsi_device
*
sdev
;
struct
scsi_cmnd
*
scmd
;
/*
* Current policy is all shosts go away on unregister.
...
...
@@ -175,10 +187,7 @@ int scsi_host_chk_and_release(struct Scsi_Host *shost)
* structures
*/
for
(
sdev
=
shost
->
host_queue
;
sdev
;
sdev
=
sdev
->
next
)
{
for
(
sdev_tp
=
scsi_devicelist
;
sdev_tp
;
sdev_tp
=
sdev_tp
->
next
)
if
(
sdev_tp
->
detach
)
(
*
sdev_tp
->
detach
)
(
sdev
);
scsi_detach_device
(
sdev
);
/* If something still attached, punt */
if
(
sdev
->
attached
)
{
...
...
@@ -186,10 +195,6 @@ int scsi_host_chk_and_release(struct Scsi_Host *shost)
sdev
->
attached
);
return
1
;
}
if
(
shost
->
hostt
->
slave_detach
)
(
*
shost
->
hostt
->
slave_detach
)
(
sdev
);
devfs_unregister
(
sdev
->
de
);
device_unregister
(
&
sdev
->
sdev_driverfs_dev
);
}
...
...
@@ -198,7 +203,6 @@ int scsi_host_chk_and_release(struct Scsi_Host *shost)
for
(
sdev
=
shost
->
host_queue
;
sdev
;
sdev
=
shost
->
host_queue
)
{
scsi_release_commandblocks
(
sdev
);
blk_cleanup_queue
(
&
sdev
->
request_queue
);
/* Next free up the Scsi_Device structures for this host */
shost
->
host_queue
=
sdev
->
next
;
...
...
@@ -207,18 +211,30 @@ int scsi_host_chk_and_release(struct Scsi_Host *shost)
kfree
(
sdev
);
}
/* Remove the instance of the individual hosts */
pcount
=
scsi_hosts_registered
;
if
(
shost
->
hostt
->
release
)
(
*
shost
->
hostt
->
release
)
(
shost
);
else
{
scsi_host_generic_release
(
shost
);
}
return
0
;
}
if
(
pcount
==
scsi_hosts_registered
)
scsi_unregister
(
shost
);
int
scsi_add_host
(
struct
Scsi_Host
*
shost
)
{
Scsi_Host_Template
*
sht
=
shost
->
hostt
;
struct
scsi_device
*
sdev
;
int
error
=
0
;
return
0
;
printk
(
KERN_INFO
"scsi%d : %s
\n
"
,
shost
->
host_no
,
sht
->
info
?
sht
->
info
(
shost
)
:
sht
->
name
);
device_register
(
&
shost
->
host_driverfs_dev
);
scan_scsis
(
shost
,
0
,
0
,
0
,
0
);
for
(
sdev
=
shost
->
host_queue
;
sdev
;
sdev
=
sdev
->
next
)
{
if
(
sdev
->
host
->
hostt
!=
sht
)
continue
;
/* XXX(hch): can this really happen? */
error
=
scsi_attach_device
(
sdev
);
if
(
error
)
break
;
}
return
error
;
}
/**
...
...
@@ -459,7 +475,6 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template *shost_tp, int xtr_bytes)
return
shost
;
}
/**
* scsi_register_host - register a low level host driver
* @shost_tp: pointer to a scsi host driver template
...
...
@@ -469,13 +484,8 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template *shost_tp, int xtr_bytes)
**/
int
scsi_register_host
(
Scsi_Host_Template
*
shost_tp
)
{
int
cur_cnt
;
Scsi_Device
*
sdev
;
struct
Scsi_Device_Template
*
sdev_tp
;
struct
list_head
*
lh
;
struct
Scsi_Host
*
shost
;
INIT_LIST_HEAD
(
&
shost_tp
->
shtp_list
);
int
cur_cnt
;
/*
* Check no detect routine.
...
...
@@ -503,11 +513,9 @@ int scsi_register_host(Scsi_Host_Template *shost_tp)
* registration code below.
*/
shost_tp
->
detect
(
shost_tp
);
if
(
!
shost_tp
->
present
)
return
0
;
if
(
shost_tp
->
present
)
{
/*
* FIXME Who needs manual registration and why???
*/
if
(
cur_cnt
==
scsi_hosts_registered
)
{
if
(
shost_tp
->
present
>
1
)
{
printk
(
KERN_ERR
"scsi: Failure to register"
...
...
@@ -515,67 +523,29 @@ int scsi_register_host(Scsi_Host_Template *shost_tp)
scsi_unregister_host
(
shost_tp
);
return
1
;
}
/*
* The low-level driver failed to register a driver.
* We can do this now.
*
* XXX Who needs manual registration and why???
*/
if
(
scsi_register
(
shost_tp
,
0
)
==
NULL
)
{
if
(
!
scsi_register
(
shost_tp
,
0
)
)
{
printk
(
KERN_ERR
"scsi: register failed.
\n
"
);
scsi_unregister_host
(
shost_tp
);
return
1
;
}
}
list_add_tail
(
&
shost_tp
->
shtp_list
,
&
scsi_host_tmpl_list
);
/* The next step is to call scan_scsis here. This generates the
* Scsi_Devices entries
*/
list_for_each
(
lh
,
&
scsi_host_list
)
{
shost
=
list_entry
(
lh
,
struct
Scsi_Host
,
sh_list
);
if
(
shost
->
hostt
==
shost_tp
)
{
const
char
*
dm_name
;
if
(
shost_tp
->
info
)
{
dm_name
=
shost_tp
->
info
(
shost
);
}
else
{
dm_name
=
shost_tp
->
name
;
}
printk
(
KERN_INFO
"scsi%d : %s
\n
"
,
shost
->
host_no
,
dm_name
);
/* first register parent with driverfs */
device_register
(
&
shost
->
host_driverfs_dev
);
scan_scsis
(
shost
,
0
,
0
,
0
,
0
);
}
}
for
(
sdev_tp
=
scsi_devicelist
;
sdev_tp
;
sdev_tp
=
sdev_tp
->
next
)
{
if
(
sdev_tp
->
init
&&
sdev_tp
->
dev_noticed
)
(
*
sdev_tp
->
init
)
();
}
/*
* Next we create the Scsi_Cmnd structures for this host
* XXX(hch) use scsi_tp_for_each_host() once it propagates
* error returns properly.
*/
list_for_each
(
lh
,
&
scsi_host_list
)
{
shost
=
list_entry
(
lh
,
struct
Scsi_Host
,
sh_list
);
for
(
sdev
=
shost
->
host_queue
;
sdev
;
sdev
=
sdev
->
next
)
if
(
sdev
->
host
->
hostt
==
shost_tp
)
{
scsi_build_commandblocks
(
sdev
);
if
(
sdev
->
current_queue_depth
==
0
)
list_for_each_entry
(
shost
,
&
scsi_host_list
,
sh_list
)
if
(
shost
->
hostt
==
shost_tp
)
if
(
scsi_add_host
(
shost
))
goto
out_of_space
;
for
(
sdev_tp
=
scsi_devicelist
;
sdev_tp
;
sdev_tp
=
sdev_tp
->
next
)
if
(
sdev_tp
->
attach
)
(
*
sdev_tp
->
attach
)
(
sdev
);
if
(
!
sdev
->
attached
)
{
scsi_release_commandblocks
(
sdev
);
}
}
}
}
return
0
;
...
...
@@ -608,20 +578,12 @@ int scsi_unregister_host(Scsi_Host_Template *shost_tp)
pcount
=
scsi_hosts_registered
;
scsi_tp_for_each_host
(
shost_tp
,
scsi_
host_chk_and_release
);
scsi_tp_for_each_host
(
shost_tp
,
scsi_
remove_legacy_host
);
if
(
pcount
!=
scsi_hosts_registered
)
printk
(
KERN_INFO
"scsi : %d host%s left.
\n
"
,
scsi_hosts_registered
,
(
scsi_hosts_registered
==
1
)
?
""
:
"s"
);
/*
* Remove it from the list if all
* hosts were successfully removed (ie preset == 0)
*/
if
(
!
shost_tp
->
present
)
{
list_del
(
&
shost_tp
->
shtp_list
);
}
MOD_DEC_USE_COUNT
;
unlock_kernel
();
...
...
drivers/scsi/hosts.h
View file @
49ce412f
...
...
@@ -57,9 +57,6 @@ typedef struct scsi_disk Disk;
typedef
struct
SHT
{
struct
list_head
shtp_list
;
/* Used with loadable modules so that we know when it is safe to unload */
struct
module
*
module
;
...
...
@@ -96,12 +93,6 @@ typedef struct SHT
*/
int
(
*
detect
)(
struct
SHT
*
);
/*
* This function is only used by one driver and will be going away
* once it switches over to using the slave_detach() function instead.
*/
int
(
*
revoke
)(
Scsi_Device
*
);
/* Used with loadable modules to unload the host structures. Note:
* there is a default action built into the modules code which may
* be sufficient for most host adapters. Thus you may not have to supply
...
...
@@ -520,8 +511,6 @@ typedef struct SHN
unsigned
short
host_registered
;
}
Scsi_Host_Name
;
extern
struct
Scsi_Device_Template
*
scsi_devicelist
;
extern
void
scsi_proc_host_mkdir
(
Scsi_Host_Template
*
);
extern
void
scsi_proc_host_add
(
struct
Scsi_Host
*
);
extern
void
scsi_proc_host_rm
(
struct
Scsi_Host
*
);
...
...
@@ -533,8 +522,6 @@ extern void scsi_proc_host_rm(struct Scsi_Host *);
extern
int
next_scsi_host
;
unsigned
int
scsi_init
(
void
);
extern
struct
Scsi_Host
*
scsi_register
(
Scsi_Host_Template
*
,
int
);
extern
void
scsi_unregister
(
struct
Scsi_Host
*
);
extern
void
scsi_register_blocked_host
(
struct
Scsi_Host
*
);
extern
void
scsi_deregister_blocked_host
(
struct
Scsi_Host
*
);
...
...
@@ -567,13 +554,7 @@ struct Scsi_Device_Template
const
char
*
tag
;
struct
module
*
module
;
/* Used for loadable modules */
unsigned
char
scsi_type
;
unsigned
int
nr_dev
;
/* Number currently attached */
unsigned
int
dev_noticed
;
/* Number of devices detected. */
unsigned
int
dev_max
;
/* Current size of arrays */
unsigned
blk
:
1
;
/* 0 if character device */
int
(
*
detect
)(
Scsi_Device
*
);
/* Returns 1 if we can attach this device */
int
(
*
init
)(
void
);
/* Sizes arrays based upon number of devices
* detected */
int
(
*
attach
)(
Scsi_Device
*
);
/* Attach devices to arrays */
void
(
*
detach
)(
Scsi_Device
*
);
int
(
*
init_command
)(
Scsi_Cmnd
*
);
/* Used by new queueing code.
...
...
@@ -585,10 +566,26 @@ void scsi_initialize_queue(Scsi_Device *, struct Scsi_Host *);
/*
*
D
river registration/unregistration.
*
Highlevel d
river registration/unregistration.
*/
extern
int
scsi_register_device
(
struct
Scsi_Device_Template
*
);
extern
int
scsi_unregister_device
(
struct
Scsi_Device_Template
*
);
/*
* HBA allocation/freeing.
*/
extern
struct
Scsi_Host
*
scsi_register
(
Scsi_Host_Template
*
,
int
);
extern
void
scsi_unregister
(
struct
Scsi_Host
*
);
/*
* HBA registration/unregistration.
*/
extern
int
scsi_add_host
(
struct
Scsi_Host
*
);
extern
int
scsi_remove_host
(
struct
Scsi_Host
*
);
/*
* Legacy HBA template registration/unregistration.
*/
extern
int
scsi_register_host
(
Scsi_Host_Template
*
);
extern
int
scsi_unregister_host
(
Scsi_Host_Template
*
);
...
...
@@ -605,28 +602,6 @@ extern void scsi_host_busy_inc(struct Scsi_Host *, Scsi_Device *);
extern
void
scsi_host_busy_dec_and_test
(
struct
Scsi_Host
*
,
Scsi_Device
*
);
extern
void
scsi_host_failed_inc_and_test
(
struct
Scsi_Host
*
);
/*
* This is an ugly hack. If we expect to be able to load devices at run time,
* we need to leave extra room in some of the data structures. Doing a
* realloc to enlarge the structures would be riddled with race conditions,
* so until a better solution is discovered, we use this crude approach
*
* Even bigger hack for SparcSTORAGE arrays. Those are at least 6 disks, but
* usually up to 30 disks, so everyone would need to change this. -jj
*
* Note: These things are all evil and all need to go away. My plan is to
* tackle the character devices first, as there aren't any locking implications
* in the block device layer. The block devices will require more work.
*
* The generics driver has been updated to resize as required. So as the tape
* driver. Two down, two more to go.
*/
#ifndef CONFIG_SR_EXTRA_DEVS
#define CONFIG_SR_EXTRA_DEVS 2
#endif
#define SR_EXTRA_DEVS CONFIG_SR_EXTRA_DEVS
/**
* scsi_find_device - find a device given the host
* @shost: SCSI host pointer
...
...
drivers/scsi/megaraid.c
View file @
49ce412f
...
...
@@ -2865,16 +2865,14 @@ static int mega_findCard (Scsi_Host_Template * pHostTmpl,
pciDevFun
=
pdev
->
devfn
;
#endif
if
((
flag
&
BOARD_QUARTZ
)
&&
(
skip_id
==
-
1
))
{
pcibios_read_config_word
(
pciBus
,
pciDevFun
,
PCI_CONF_AMISIG
,
&
magic
);
pci_read_config_word
(
pdev
,
PCI_CONF_AMISIG
,
&
magic
);
if
((
magic
!=
AMI_SIGNATURE
)
&&
(
magic
!=
AMI_SIGNATURE_471
))
{
pciIdx
++
;
continue
;
/* not an AMI board */
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
pcibios_read_config_dword
(
pciBus
,
pciDevFun
,
PCI_CONF_AMISIG64
,
&
magic64
);
pci_read_config_dword
(
pdev
,
PCI_CONF_AMISIG64
,
&
magic64
);
if
(
magic64
==
AMI_64BIT_SIGNATURE
)
flag
|=
BOARD_64BIT
;
...
...
@@ -3215,7 +3213,6 @@ int megaraid_detect (Scsi_Host_Template * pHostTmpl)
count
+=
mega_findCard
(
pHostTmpl
,
PCI_VENDOR_ID_AMI
,
PCI_DEVICE_ID_AMI_MEGARAID3
,
BOARD_QUARTZ
);
mega_reorder_hosts
();
#ifdef CONFIG_PROC_FS
if
(
count
)
{
...
...
@@ -3481,173 +3478,6 @@ mega_get_boot_ldrv(mega_host_config *megacfg)
}
static
void
mega_reorder_hosts
(
void
)
{
struct
Scsi_Host
*
shpnt
;
struct
Scsi_Host
*
shone
;
struct
Scsi_Host
*
shtwo
;
mega_host_config
*
boot_host
;
int
i
;
/*
* Find the (first) host which has it's BIOS enabled
*/
boot_host
=
NULL
;
for
(
i
=
0
;
i
<
MAX_CONTROLLERS
;
i
++
)
{
if
(
mega_hbas
[
i
].
is_bios_enabled
)
{
boot_host
=
mega_hbas
[
i
].
hostdata_addr
;
break
;
}
}
if
(
boot_host
==
NULL
)
{
printk
(
KERN_WARNING
"megaraid: no BIOS enabled.
\n
"
);
return
;
}
/*
* Traverse through the list of SCSI hosts for our HBA locations
*/
shone
=
shtwo
=
NULL
;
for
(
shpnt
=
scsi_hostlist
;
shpnt
;
shpnt
=
shpnt
->
next
)
{
/* Is it one of ours? */
for
(
i
=
0
;
i
<
MAX_CONTROLLERS
;
i
++
)
{
if
((
mega_host_config
*
)
shpnt
->
hostdata
==
mega_hbas
[
i
].
hostdata_addr
)
{
/* Does this one has BIOS enabled */
if
(
mega_hbas
[
i
].
hostdata_addr
==
boot_host
)
{
/* Are we first */
if
(
shtwo
==
NULL
)
/* Yes! */
return
;
else
{
/* :-( */
shone
=
shpnt
;
}
}
else
{
if
(
!
shtwo
)
{
/* were we here before? xchng first */
shtwo
=
shpnt
;
}
}
break
;
}
}
/*
* Have we got the boot host and one which does not have the bios
* enabled.
*/
if
(
shone
&&
shtwo
)
break
;
}
if
(
shone
&&
shtwo
)
{
mega_swap_hosts
(
shone
,
shtwo
);
}
return
;
}
static
void
mega_swap_hosts
(
struct
Scsi_Host
*
shone
,
struct
Scsi_Host
*
shtwo
)
{
struct
Scsi_Host
*
prevtoshtwo
;
struct
Scsi_Host
*
prevtoshone
;
struct
Scsi_Host
*
save
=
NULL
;;
/* Are these two nodes adjacent */
if
(
shtwo
->
next
==
shone
)
{
if
(
shtwo
==
scsi_hostlist
&&
shone
->
next
==
NULL
)
{
/* just two nodes */
scsi_hostlist
=
shone
;
shone
->
next
=
shtwo
;
shtwo
->
next
=
NULL
;
}
else
if
(
shtwo
==
scsi_hostlist
)
{
/* first two nodes of the list */
scsi_hostlist
=
shone
;
shtwo
->
next
=
shone
->
next
;
scsi_hostlist
->
next
=
shtwo
;
}
else
if
(
shone
->
next
==
NULL
)
{
/* last two nodes of the list */
prevtoshtwo
=
scsi_hostlist
;
while
(
prevtoshtwo
->
next
!=
shtwo
)
prevtoshtwo
=
prevtoshtwo
->
next
;
prevtoshtwo
->
next
=
shone
;
shone
->
next
=
shtwo
;
shtwo
->
next
=
NULL
;
}
else
{
prevtoshtwo
=
scsi_hostlist
;
while
(
prevtoshtwo
->
next
!=
shtwo
)
prevtoshtwo
=
prevtoshtwo
->
next
;
prevtoshtwo
->
next
=
shone
;
shtwo
->
next
=
shone
->
next
;
shone
->
next
=
shtwo
;
}
}
else
if
(
shtwo
==
scsi_hostlist
&&
shone
->
next
==
NULL
)
{
/* shtwo at head, shone at tail, not adjacent */
prevtoshone
=
scsi_hostlist
;
while
(
prevtoshone
->
next
!=
shone
)
prevtoshone
=
prevtoshone
->
next
;
scsi_hostlist
=
shone
;
shone
->
next
=
shtwo
->
next
;
prevtoshone
->
next
=
shtwo
;
shtwo
->
next
=
NULL
;
}
else
if
(
shtwo
==
scsi_hostlist
&&
shone
->
next
!=
NULL
)
{
/* shtwo at head, shone is not at tail */
prevtoshone
=
scsi_hostlist
;
while
(
prevtoshone
->
next
!=
shone
)
prevtoshone
=
prevtoshone
->
next
;
scsi_hostlist
=
shone
;
prevtoshone
->
next
=
shtwo
;
save
=
shtwo
->
next
;
shtwo
->
next
=
shone
->
next
;
shone
->
next
=
save
;
}
else
if
(
shone
->
next
==
NULL
)
{
/* shtwo not at head, shone at tail */
prevtoshtwo
=
scsi_hostlist
;
prevtoshone
=
scsi_hostlist
;
while
(
prevtoshtwo
->
next
!=
shtwo
)
prevtoshtwo
=
prevtoshtwo
->
next
;
while
(
prevtoshone
->
next
!=
shone
)
prevtoshone
=
prevtoshone
->
next
;
prevtoshtwo
->
next
=
shone
;
shone
->
next
=
shtwo
->
next
;
prevtoshone
->
next
=
shtwo
;
shtwo
->
next
=
NULL
;
}
else
{
prevtoshtwo
=
scsi_hostlist
;
prevtoshone
=
scsi_hostlist
;
save
=
NULL
;;
while
(
prevtoshtwo
->
next
!=
shtwo
)
prevtoshtwo
=
prevtoshtwo
->
next
;
while
(
prevtoshone
->
next
!=
shone
)
prevtoshone
=
prevtoshone
->
next
;
prevtoshtwo
->
next
=
shone
;
save
=
shone
->
next
;
shone
->
next
=
shtwo
->
next
;
prevtoshone
->
next
=
shtwo
;
shtwo
->
next
=
save
;
}
return
;
}
static
inline
void
mega_freeSgList
(
mega_host_config
*
megaCfg
)
{
int
i
;
...
...
@@ -4235,7 +4065,7 @@ int megaraid_biosparam (struct scsi_device *sdev, struct block_device *bdev,
/* Default heads (64) & sectors (32) */
heads
=
64
;
sectors
=
32
;
cylinders
=
(
unsigned
long
)
capacity
/
(
heads
*
sectors
)
;
cylinders
=
(
unsigned
long
)
capacity
>>
11
;
/* Handle extended translation size for logical drives > 1Gb */
if
(
capacity
>=
0x200000
)
{
...
...
@@ -4293,7 +4123,6 @@ mega_partsize(struct block_device *bdev, sector_t capacity, int *geom)
struct
partition
*
p
,
*
largest
=
NULL
;
int
i
,
largest_cyl
;
int
heads
,
cyls
,
sectors
;
int
capacity
=
capacity
;
unsigned
char
*
buf
;
if
(
!
(
buf
=
scsi_bios_ptable
(
bdev
)))
...
...
@@ -4324,7 +4153,7 @@ mega_partsize(struct block_device *bdev, sector_t capacity, int *geom)
return
-
1
;
}
cyls
=
capacity
/
(
heads
*
sectors
);
cyls
=
(
unsigned
long
)
capacity
/
(
heads
*
sectors
);
geom
[
0
]
=
heads
;
geom
[
1
]
=
sectors
;
...
...
@@ -4683,12 +4512,7 @@ static int megadev_ioctl (struct inode *inode, struct file *filep,
/*
* Find this host
*/
for
(
shpnt
=
scsi_hostlist
;
shpnt
;
shpnt
=
shpnt
->
next
)
{
if
(
shpnt
->
hostdata
==
(
unsigned
long
*
)
megaCtlrs
[
adapno
]
)
{
megacfg
=
(
mega_host_config
*
)
shpnt
->
hostdata
;
break
;
}
}
shpnt
=
megaCtlrs
[
adapno
]
->
host
;
if
(
shpnt
==
NULL
)
return
-
ENODEV
;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
...
...
@@ -4803,12 +4627,7 @@ static int megadev_ioctl (struct inode *inode, struct file *filep,
/*
* Find this host
*/
for
(
shpnt
=
scsi_hostlist
;
shpnt
;
shpnt
=
shpnt
->
next
)
{
if
(
shpnt
->
hostdata
==
(
unsigned
long
*
)
megaCtlrs
[
adapno
]
)
{
megacfg
=
(
mega_host_config
*
)
shpnt
->
hostdata
;
break
;
}
}
shpnt
=
megaCtlrs
[
adapno
]
->
host
;
if
(
shpnt
==
NULL
)
return
-
ENODEV
;
/*
...
...
drivers/scsi/megaraid.h
View file @
49ce412f
...
...
@@ -214,8 +214,6 @@
info: megaraid_info,
/* Driver Info Function */
\
command: megaraid_command,
/* Command Function */
\
queuecommand: megaraid_queue,
/* Queue Command Function */
\
abort: megaraid_abort,
/* Abort Command Function */
\
reset: megaraid_reset,
/* Reset Command Function */
\
bios_param: megaraid_biosparam,
/* Disk BIOS Parameters */
\
can_queue: MAX_COMMANDS,
/* Can Queue */
\
this_id: 7,
/* HBA Target ID */
\
...
...
@@ -989,8 +987,6 @@ static void enq_scb_freelist (mega_host_config *, mega_scb *,
int
lock
,
int
intr
);
static
int
mega_is_bios_enabled
(
mega_host_config
*
);
static
void
mega_reorder_hosts
(
void
);
static
void
mega_swap_hosts
(
struct
Scsi_Host
*
,
struct
Scsi_Host
*
);
static
void
mega_create_proc_entry
(
int
index
,
struct
proc_dir_entry
*
);
static
int
mega_support_ext_cdb
(
mega_host_config
*
);
...
...
drivers/scsi/osst.c
View file @
49ce412f
...
...
@@ -156,6 +156,10 @@ static int osst_attach(Scsi_Device *);
static
int
osst_detect
(
Scsi_Device
*
);
static
void
osst_detach
(
Scsi_Device
*
);
static
int
osst_dev_noticed
;
static
int
osst_nr_dev
;
static
int
osst_dev_max
;
struct
Scsi_Device_Template
osst_template
=
{
module:
THIS_MODULE
,
...
...
@@ -163,7 +167,6 @@ struct Scsi_Device_Template osst_template =
tag:
"osst"
,
scsi_type:
TYPE_TAPE
,
detect:
osst_detect
,
init:
osst_init
,
attach:
osst_attach
,
detach:
osst_detach
};
...
...
@@ -4155,7 +4158,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
char
*
name
;
int
mode
=
TAPE_MODE
(
inode
->
i_rdev
);
if
(
dev
>=
osst_
template
.
dev_max
||
(
STp
=
os_scsi_tapes
[
dev
])
==
NULL
||
!
STp
->
device
)
if
(
dev
>=
osst_dev_max
||
(
STp
=
os_scsi_tapes
[
dev
])
==
NULL
||
!
STp
->
device
)
return
(
-
ENXIO
);
filp
->
private_data
=
STp
;
...
...
@@ -4980,7 +4983,7 @@ static OSST_buffer * new_tape_buffer( int from_initialization, int need_dma )
int
i
,
priority
,
b_size
,
order
,
got
=
0
,
segs
=
0
;
OSST_buffer
*
tb
;
if
(
osst_nbr_buffers
>=
osst_
template
.
dev_max
)
if
(
osst_nbr_buffers
>=
osst_dev_max
)
return
NULL
;
/* Should never happen */
if
(
from_initialization
)
...
...
@@ -5411,26 +5414,31 @@ static int osst_attach(Scsi_Device * SDp)
if
(
SDp
->
type
!=
TYPE_TAPE
||
!
osst_supports
(
SDp
))
return
1
;
osst_init
();
disk
=
alloc_disk
(
1
);
if
(
!
disk
)
return
1
;
if
(
osst_template
.
nr_dev
>=
osst_template
.
dev_max
)
{
SDp
->
attached
--
;
if
(
osst_nr_dev
>=
osst_dev_max
)
{
put_disk
(
disk
);
return
1
;
}
if
(
scsi_slave_attach
(
SDp
))
return
1
;
/* find a free minor number */
for
(
i
=
0
;
os_scsi_tapes
[
i
]
&&
i
<
osst_
template
.
dev_max
;
i
++
);
if
(
i
>=
osst_
template
.
dev_max
)
panic
(
"Scsi_devices corrupt (osst)"
);
for
(
i
=
0
;
os_scsi_tapes
[
i
]
&&
i
<
osst_dev_max
;
i
++
);
if
(
i
>=
osst_dev_max
)
panic
(
"Scsi_devices corrupt (osst)"
);
/* allocate a OS_Scsi_Tape for this device */
tpnt
=
(
OS_Scsi_Tape
*
)
kmalloc
(
sizeof
(
OS_Scsi_Tape
),
GFP_ATOMIC
);
if
(
tpnt
==
NULL
)
{
SDp
->
attached
--
;
printk
(
KERN_WARNING
"osst :W: Can't allocate device descriptor.
\n
"
);
put_disk
(
disk
);
scsi_slave_detach
(
SDp
);
return
1
;
}
memset
(
tpnt
,
0
,
sizeof
(
OS_Scsi_Tape
));
...
...
@@ -5547,7 +5555,7 @@ static int osst_attach(Scsi_Device * SDp)
tpnt
->
density_changed
=
tpnt
->
compression_changed
=
tpnt
->
blksize_changed
=
FALSE
;
init_MUTEX
(
&
tpnt
->
lock
);
osst_
template
.
nr_dev
++
;
osst_nr_dev
++
;
printk
(
KERN_INFO
"osst :I: Attached OnStream %.5s tape at scsi%d, channel %d, id %d, lun %d as %s
\n
"
,
...
...
@@ -5561,7 +5569,7 @@ static int osst_detect(Scsi_Device * SDp)
if
(
SDp
->
type
!=
TYPE_TAPE
)
return
0
;
if
(
!
osst_supports
(
SDp
)
)
return
0
;
osst_
template
.
dev_noticed
++
;
osst_dev_noticed
++
;
return
1
;
}
...
...
@@ -5572,7 +5580,7 @@ static int osst_init()
{
int
i
;
if
(
osst_
template
.
dev_noticed
==
0
)
if
(
osst_dev_noticed
==
0
)
return
0
;
if
(
!
osst_registered
)
{
...
...
@@ -5585,10 +5593,10 @@ static int osst_init()
if
(
os_scsi_tapes
)
return
0
;
osst_
template
.
dev_max
=
OSST_MAX_TAPES
;
if
(
osst_
template
.
dev_max
>
128
/
ST_NBR_MODES
)
osst_dev_max
=
OSST_MAX_TAPES
;
if
(
osst_dev_max
>
128
/
ST_NBR_MODES
)
printk
(
KERN_INFO
"osst :I: Only %d tapes accessible.
\n
"
,
128
/
ST_NBR_MODES
);
os_scsi_tapes
=
kmalloc
(
osst_
template
.
dev_max
*
sizeof
(
OS_Scsi_Tape
*
),
os_scsi_tapes
=
kmalloc
(
osst_dev_max
*
sizeof
(
OS_Scsi_Tape
*
),
GFP_ATOMIC
);
if
(
!
os_scsi_tapes
)
{
printk
(
KERN_ERR
"osst :W: Unable to allocate array for OnStream SCSI tapes.
\n
"
);
...
...
@@ -5596,11 +5604,11 @@ static int osst_init()
return
1
;
}
for
(
i
=
0
;
i
<
osst_
template
.
dev_max
;
++
i
)
for
(
i
=
0
;
i
<
osst_dev_max
;
++
i
)
os_scsi_tapes
[
i
]
=
NULL
;
/* Allocate the buffer pointers */
osst_buffers
=
kmalloc
(
osst_
template
.
dev_max
*
sizeof
(
OSST_buffer
*
),
osst_buffers
=
kmalloc
(
osst_dev_max
*
sizeof
(
OSST_buffer
*
),
GFP_ATOMIC
);
if
(
!
osst_buffers
)
{
printk
(
KERN_ERR
"osst :W: Unable to allocate tape buffer pointers.
\n
"
);
...
...
@@ -5628,7 +5636,7 @@ static void osst_detach(Scsi_Device * SDp)
int
mode
;
#endif
for
(
i
=
0
;
i
<
osst_
template
.
dev_max
;
i
++
)
{
for
(
i
=
0
;
i
<
osst_dev_max
;
i
++
)
{
tpnt
=
os_scsi_tapes
[
i
];
if
(
tpnt
!=
NULL
&&
tpnt
->
device
==
SDp
)
{
tpnt
->
device
=
NULL
;
...
...
@@ -5643,9 +5651,9 @@ static void osst_detach(Scsi_Device * SDp)
put_disk
(
tpnt
->
disk
);
kfree
(
tpnt
);
os_scsi_tapes
[
i
]
=
NULL
;
SDp
->
attached
--
;
osst_
template
.
nr_dev
--
;
osst_
template
.
dev_noticed
--
;
scsi_slave_detach
(
SDp
)
;
osst_nr_dev
--
;
osst_dev_noticed
--
;
return
;
}
}
...
...
@@ -5667,7 +5675,7 @@ static void __exit exit_osst (void)
unregister_chrdev
(
MAJOR_NR
,
"osst"
);
osst_registered
--
;
if
(
os_scsi_tapes
)
{
for
(
i
=
0
;
i
<
osst_
template
.
dev_max
;
++
i
)
{
for
(
i
=
0
;
i
<
osst_dev_max
;
++
i
)
{
STp
=
os_scsi_tapes
[
i
];
if
(
!
STp
)
continue
;
...
...
@@ -5689,7 +5697,7 @@ static void __exit exit_osst (void)
kfree
(
osst_buffers
);
}
}
osst_
template
.
dev_max
=
0
;
osst_dev_max
=
0
;
printk
(
KERN_INFO
"osst :I: Unloaded.
\n
"
);
}
...
...
drivers/scsi/scsi.c
View file @
49ce412f
...
...
@@ -132,6 +132,12 @@ struct softscsi_data {
static
struct
softscsi_data
softscsi_data
[
NR_CPUS
]
__cacheline_aligned
;
/*
* List of all highlevel drivers.
*/
static
struct
Scsi_Device_Template
*
scsi_devicelist
;
static
DECLARE_RWSEM
(
scsi_devicelist_mutex
);
/*
* Note - the initial logging level can be set here to log events at boot time.
* After the system is up, you may enable logging via the /proc interface.
...
...
@@ -1660,10 +1666,6 @@ void scsi_adjust_queue_depth(Scsi_Device *SDpnt, int tagged, int tags)
break
;
}
spin_unlock_irqrestore
(
&
device_request_lock
,
flags
);
if
(
SDpnt
->
current_queue_depth
==
0
)
{
scsi_build_commandblocks
(
SDpnt
);
}
}
#ifdef CONFIG_PROC_FS
...
...
@@ -1720,7 +1722,6 @@ static int scsi_proc_info(char *buffer, char **start, off_t offset, int length)
static
int
proc_scsi_gen_write
(
struct
file
*
file
,
const
char
*
buf
,
unsigned
long
length
,
void
*
data
)
{
struct
Scsi_Device_Template
*
SDTpnt
;
Scsi_Device
*
scd
;
struct
Scsi_Host
*
HBA_ptr
;
char
*
p
;
...
...
@@ -1926,24 +1927,10 @@ static int proc_scsi_gen_write(struct file * file, const char * buf,
if
(
scd
->
access_count
)
goto
out
;
SDTpnt
=
scsi_devicelist
;
while
(
SDTpnt
!=
NULL
)
{
if
(
SDTpnt
->
detach
)
(
*
SDTpnt
->
detach
)
(
scd
);
SDTpnt
=
SDTpnt
->
next
;
}
scsi_detach_device
(
scd
);
if
(
scd
->
attached
==
0
)
{
/*
* Nobody is using this device any more.
* Free all of the command structures.
*/
if
(
HBA_ptr
->
hostt
->
revoke
)
HBA_ptr
->
hostt
->
revoke
(
scd
);
if
(
HBA_ptr
->
hostt
->
slave_detach
)
(
*
HBA_ptr
->
hostt
->
slave_detach
)
(
scd
);
devfs_unregister
(
scd
->
de
);
scsi_release_commandblocks
(
scd
);
/* Now we can remove the device structure */
if
(
scd
->
next
!=
NULL
)
...
...
@@ -1971,6 +1958,109 @@ static int proc_scsi_gen_write(struct file * file, const char * buf,
}
#endif
void
scsi_detect_device
(
struct
scsi_device
*
sdev
)
{
struct
Scsi_Device_Template
*
sdt
;
down_read
(
&
scsi_devicelist_mutex
);
for
(
sdt
=
scsi_devicelist
;
sdt
;
sdt
=
sdt
->
next
)
if
(
sdt
->
detect
)
(
*
sdt
->
detect
)(
sdev
);
up_read
(
&
scsi_devicelist_mutex
);
}
int
scsi_attach_device
(
struct
scsi_device
*
sdev
)
{
struct
Scsi_Device_Template
*
sdt
;
down_read
(
&
scsi_devicelist_mutex
);
for
(
sdt
=
scsi_devicelist
;
sdt
;
sdt
=
sdt
->
next
)
if
(
sdt
->
attach
)
/*
* XXX check result when the upper level attach
* return values are fixed, and on failure goto
* fail.
*/
(
*
sdt
->
attach
)
(
sdev
);
up_read
(
&
scsi_devicelist_mutex
);
return
0
;
fail:
printk
(
KERN_ERR
"%s: Allocation failure during SCSI scanning, "
"some SCSI devices might not be configured
\n
"
,
__FUNCTION__
);
return
-
ENOMEM
;
}
void
scsi_detach_device
(
struct
scsi_device
*
sdev
)
{
struct
Scsi_Device_Template
*
sdt
;
down_read
(
&
scsi_devicelist_mutex
);
for
(
sdt
=
scsi_devicelist
;
sdt
;
sdt
=
sdt
->
next
)
if
(
sdt
->
detach
)
(
*
sdt
->
detach
)(
sdev
);
up_read
(
&
scsi_devicelist_mutex
);
}
/*
* Function: scsi_slave_attach()
*
* Purpose: Called from the upper level driver attach to handle common
* attach code.
*
* Arguments: sdev - scsi_device to attach
*
* Returns: 1 on error, 0 on succes
*
* Lock Status: Protected via scsi_devicelist_mutex.
*/
int
scsi_slave_attach
(
struct
scsi_device
*
sdev
)
{
if
(
sdev
->
attached
++
==
0
)
{
/*
* No one was attached.
*/
scsi_build_commandblocks
(
sdev
);
if
(
sdev
->
current_queue_depth
==
0
)
{
printk
(
KERN_ERR
"scsi: Allocation failure during"
" attach, some SCSI devices might not be"
" configured
\n
"
);
return
1
;
}
if
(
sdev
->
host
->
hostt
->
slave_attach
!=
NULL
)
{
if
(
sdev
->
host
->
hostt
->
slave_attach
(
sdev
)
!=
0
)
{
printk
(
KERN_INFO
"scsi: failed low level driver"
" attach, some SCSI device might not be"
" configured
\n
"
);
scsi_release_commandblocks
(
sdev
);
return
1
;
}
}
else
if
(
sdev
->
host
->
cmd_per_lun
!=
0
)
scsi_adjust_queue_depth
(
sdev
,
0
,
sdev
->
host
->
cmd_per_lun
);
}
return
0
;
}
/*
* Function: scsi_slave_detach()
*
* Purpose: Called from the upper level driver attach to handle common
* detach code.
*
* Arguments: sdev - struct scsi_device to detach
*
* Lock Status: Protected via scsi_devicelist_mutex.
*/
void
scsi_slave_detach
(
struct
scsi_device
*
sdev
)
{
if
(
--
sdev
->
attached
==
0
)
{
if
(
sdev
->
host
->
hostt
->
slave_detach
!=
NULL
)
sdev
->
host
->
hostt
->
slave_detach
(
sdev
);
scsi_release_commandblocks
(
sdev
);
}
}
/*
* This entry point should be called by a loadable module if it is trying
* add a high level scsi driver to the system.
...
...
@@ -1989,8 +2079,10 @@ int scsi_register_device(struct Scsi_Device_Template *tpnt)
if
(
tpnt
->
next
)
return
1
;
down_write
(
&
scsi_devicelist_mutex
);
tpnt
->
next
=
scsi_devicelist
;
scsi_devicelist
=
tpnt
;
up_write
(
&
scsi_devicelist_mutex
);
tpnt
->
scsi_driverfs_driver
.
name
=
(
char
*
)
tpnt
->
tag
;
tpnt
->
scsi_driverfs_driver
.
bus
=
&
scsi_driverfs_bus_type
;
...
...
@@ -2006,18 +2098,10 @@ int scsi_register_device(struct Scsi_Device_Template *tpnt)
for
(
SDpnt
=
shpnt
->
host_queue
;
SDpnt
;
SDpnt
=
SDpnt
->
next
)
{
if
(
tpnt
->
detect
)
SDpnt
->
attached
+=
(
*
tpnt
->
detect
)
(
SDpnt
);
(
*
tpnt
->
detect
)
(
SDpnt
);
}
}
/*
* If any of the devices would match this driver, then perform the
* init function.
*/
if
(
tpnt
->
init
&&
tpnt
->
dev_noticed
)
if
((
*
tpnt
->
init
)
())
return
1
;
/*
* Now actually connect the devices to the new driver.
*/
...
...
@@ -2025,22 +2109,14 @@ int scsi_register_device(struct Scsi_Device_Template *tpnt)
shpnt
=
scsi_host_get_next
(
shpnt
))
{
for
(
SDpnt
=
shpnt
->
host_queue
;
SDpnt
;
SDpnt
=
SDpnt
->
next
)
{
scsi_build_commandblocks
(
SDpnt
);
if
(
SDpnt
->
current_queue_depth
==
0
)
{
out_of_space
=
1
;
continue
;
}
if
(
tpnt
->
attach
)
(
*
tpnt
->
attach
)
(
SDpnt
);
/*
* If this driver attached to the device, and don't have any
* command blocks for this device, allocate some.
* XXX check result when the upper level
* attach return values are fixed, and
* stop attaching on failure.
*/
if
(
SDpnt
->
attached
)
SDpnt
->
online
=
TRUE
;
else
scsi_release_commandblocks
(
SDpnt
);
(
*
tpnt
->
attach
)
(
SDpnt
);
}
}
...
...
@@ -2080,22 +2156,12 @@ int scsi_unregister_device(struct Scsi_Device_Template *tpnt)
SDpnt
=
SDpnt
->
next
)
{
if
(
tpnt
->
detach
)
(
*
tpnt
->
detach
)
(
SDpnt
);
if
(
SDpnt
->
attached
==
0
)
{
SDpnt
->
online
=
FALSE
;
/*
* Nobody is using this device any more. Free all of the
* command structures.
*/
if
(
shpnt
->
hostt
->
slave_detach
)
(
*
shpnt
->
hostt
->
slave_detach
)
(
SDpnt
);
scsi_release_commandblocks
(
SDpnt
);
}
}
}
/*
* Extract the template from the linked list.
*/
down_write
(
&
scsi_devicelist_mutex
);
spnt
=
scsi_devicelist
;
prev_spnt
=
NULL
;
while
(
spnt
!=
tpnt
)
{
...
...
@@ -2106,6 +2172,7 @@ int scsi_unregister_device(struct Scsi_Device_Template *tpnt)
scsi_devicelist
=
tpnt
->
next
;
else
prev_spnt
->
next
=
spnt
->
next
;
up_write
(
&
scsi_devicelist_mutex
);
MOD_DEC_USE_COUNT
;
unlock_kernel
();
...
...
drivers/scsi/scsi.h
View file @
49ce412f
...
...
@@ -466,6 +466,8 @@ extern void scsi_bottom_half_handler(void);
extern
void
scsi_release_commandblocks
(
Scsi_Device
*
SDpnt
);
extern
void
scsi_build_commandblocks
(
Scsi_Device
*
SDpnt
);
extern
void
scsi_adjust_queue_depth
(
Scsi_Device
*
,
int
,
int
);
extern
int
scsi_slave_attach
(
struct
scsi_device
*
sdev
);
extern
void
scsi_slave_detach
(
struct
scsi_device
*
sdev
);
extern
void
scsi_done
(
Scsi_Cmnd
*
SCpnt
);
extern
void
scsi_finish_command
(
Scsi_Cmnd
*
);
extern
int
scsi_retry_command
(
Scsi_Cmnd
*
);
...
...
@@ -478,6 +480,9 @@ extern void scsi_do_cmd(Scsi_Cmnd *, const void *cmnd,
int
timeout
,
int
retries
);
extern
int
scsi_dev_init
(
void
);
extern
int
scsi_mlqueue_insert
(
struct
scsi_cmnd
*
,
int
);
extern
void
scsi_detect_device
(
struct
scsi_device
*
);
extern
int
scsi_attach_device
(
struct
scsi_device
*
);
extern
void
scsi_detach_device
(
struct
scsi_device
*
);
/*
* Newer request-based interfaces.
...
...
drivers/scsi/scsi_debug.c
View file @
49ce412f
...
...
@@ -17,6 +17,7 @@
* forked for lk 2.5 series [20011216, 20020101]
* use vmalloc() more inquiry+mode_sense [20020302]
* add timers for delayed responses [20020721]
* Patrick Mansfield <patmans@us.ibm.com> max_luns+scsi_level [20021031]
*/
#include <linux/config.h>
...
...
@@ -49,7 +50,7 @@
#include "scsi_debug.h"
static
const
char
*
scsi_debug_version_str
=
"Version: 1.6
2 (20020812
)"
;
static
const
char
*
scsi_debug_version_str
=
"Version: 1.6
3 (20021103
)"
;
#define DRIVERFS_SUPPORT 1
/* comment out whole line to disable */
...
...
@@ -60,9 +61,8 @@ static const char * scsi_debug_version_str = "Version: 1.62 (20020812)";
#ifndef SCSI_CMD_WRITE_16
#define SCSI_CMD_WRITE_16 0x8a
#endif
#ifndef REPORT_LUNS
#define REPORT_LUNS 0xa0
#endif
#define SDEBUG_TAGGED_QUEUING 0
/* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */
/* A few options that we want selected */
#define DEF_NR_FAKE_DEVS 1
...
...
@@ -70,6 +70,8 @@ static const char * scsi_debug_version_str = "Version: 1.62 (20020812)";
#define DEF_FAKE_BLK0 0
#define DEF_EVERY_NTH 100
#define DEF_DELAY 1
#define DEF_MAX_LUNS 2
#define DEF_SCSI_LEVEL 3
#define DEF_OPTS 0
#define SCSI_DEBUG_OPT_NOISE 1
...
...
@@ -83,8 +85,11 @@ static int scsi_debug_opts = DEF_OPTS;
static
int
scsi_debug_every_nth
=
DEF_EVERY_NTH
;
static
int
scsi_debug_cmnd_count
=
0
;
static
int
scsi_debug_delay
=
DEF_DELAY
;
static
int
scsi_debug_max_luns
=
DEF_MAX_LUNS
;
static
int
scsi_debug_scsi_level
=
DEF_SCSI_LEVEL
;
#define NR_HOSTS_PRESENT (((scsi_debug_num_devs - 1) / 7) + 1)
/* This assumes one lun used per allocated target id */
#define N_HEAD 8
#define N_SECTOR 32
#define DEV_READONLY(TGT) (0)
...
...
@@ -118,7 +123,7 @@ struct sdebug_dev_info {
};
static
struct
sdebug_dev_info
*
devInfop
;
typedef
void
(
*
done_funct_t
)
(
Scsi_C
mnd
*
);
typedef
void
(
*
done_funct_t
)
(
struct
scsi_c
mnd
*
);
struct
sdebug_queued_cmd
{
int
in_use
;
...
...
@@ -131,7 +136,7 @@ static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE];
static
unsigned
char
*
fake_storep
;
/* ramdisk storage */
static
unsigned
char
broken
_buff
[
SDEBUG_SENSE_LEN
];
static
unsigned
char
spare
_buff
[
SDEBUG_SENSE_LEN
];
static
int
num_aborts
=
0
;
static
int
num_dev_resets
=
0
;
...
...
@@ -151,17 +156,18 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff,
static
int
resp_mode_sense
(
unsigned
char
*
cmd
,
int
target
,
unsigned
char
*
buff
,
int
bufflen
,
struct
sdebug_dev_info
*
devip
);
static
int
resp_read
(
Scsi_Cmnd
*
SCpnt
,
int
upper_blk
,
int
block
,
static
int
resp_read
(
struct
scsi_cmnd
*
SCpnt
,
int
upper_blk
,
int
block
,
int
num
,
struct
sdebug_dev_info
*
devip
);
static
int
resp_write
(
struct
scsi_cmnd
*
SCpnt
,
int
upper_blk
,
int
block
,
int
num
,
struct
sdebug_dev_info
*
devip
);
static
int
resp_write
(
Scsi_Cmnd
*
SCpnt
,
int
upper_blk
,
int
block
,
int
num
,
struct
sdebug_dev_info
*
devip
);
static
int
resp_report_luns
(
unsigned
char
*
cmd
,
unsigned
char
*
buff
,
int
bufflen
,
struct
sdebug_dev_info
*
devip
);
static
void
timer_intr_handler
(
unsigned
long
);
static
struct
sdebug_dev_info
*
devInfoReg
(
Scsi_C
mnd
*
scmd
);
static
struct
sdebug_dev_info
*
devInfoReg
(
struct
scsi_c
mnd
*
scmd
);
static
void
mk_sense_buffer
(
struct
sdebug_dev_info
*
devip
,
int
key
,
int
asc
,
int
asq
,
int
inbandLen
);
static
int
check_reset
(
Scsi_Cmnd
*
SCpnt
,
struct
sdebug_dev_info
*
devip
);
static
int
check_reset
(
struct
scsi_cmnd
*
SCpnt
,
struct
sdebug_dev_info
*
devip
);
static
int
schedule_resp
(
struct
scsi_cmnd
*
cmnd
,
struct
sdebug_dev_info
*
devip
,
done_funct_t
done
,
int
scsi_result
,
int
delta_jiff
);
...
...
@@ -188,7 +194,7 @@ static unsigned char * scatg2virt(const struct scatterlist * sclp)
}
static
int
scsi_debug_queuecommand
(
Scsi_C
mnd
*
SCpnt
,
done_funct_t
done
)
int
scsi_debug_queuecommand
(
struct
scsi_c
mnd
*
SCpnt
,
done_funct_t
done
)
{
unsigned
char
*
cmd
=
(
unsigned
char
*
)
SCpnt
->
cmnd
;
int
block
;
...
...
@@ -215,8 +221,7 @@ int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, done_funct_t done)
else
buff
=
(
unsigned
char
*
)
SCpnt
->
request_buffer
;
if
(
NULL
==
buff
)
{
printk
(
KERN_WARNING
"scsi_debug:qc: buff was NULL??
\n
"
);
buff
=
broken_buff
;
/* just point at dummy */
buff
=
spare_buff
;
/* assume cmd moves no data */
bufflen
=
SDEBUG_SENSE_LEN
;
}
...
...
@@ -226,11 +231,11 @@ int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, done_funct_t done)
return
schedule_resp
(
SCpnt
,
NULL
,
done
,
0
,
0
);
}
if
(
SCpnt
->
lun
!=
0
)
if
(
SCpnt
->
lun
>=
scsi_debug_max_luns
)
return
schedule_resp
(
SCpnt
,
NULL
,
done
,
DID_NO_CONNECT
<<
16
,
0
);
#if 0
printk(KERN_INFO "sdebug:qc: host_no=%
d, id=%d
, sdp=%p, cmd=0x%x\n",
printk(KERN_INFO "sdebug:qc: host_no=%
u, id=%u
, sdp=%p, cmd=0x%x\n",
(int)SCpnt->device->host->host_no, (int)SCpnt->device->id,
SCpnt->device, (int)*cmd);
#endif
...
...
@@ -248,9 +253,6 @@ int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, done_funct_t done)
switch
(
*
cmd
)
{
case
INQUIRY
:
/* mandatory */
/* assume INQUIRY called first so setup max_cmd_len */
if
(
SCpnt
->
host
->
max_cmd_len
!=
SCSI_DEBUG_MAX_CMD_LEN
)
SCpnt
->
host
->
max_cmd_len
=
SCSI_DEBUG_MAX_CMD_LEN
;
errsts
=
resp_inquiry
(
cmd
,
target
,
buff
,
bufflen
,
devip
);
break
;
case
REQUEST_SENSE
:
/* mandatory */
...
...
@@ -380,6 +382,9 @@ int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, done_funct_t done)
case
MODE_SENSE_10
:
errsts
=
resp_mode_sense
(
cmd
,
target
,
buff
,
bufflen
,
devip
);
break
;
case
SYNCHRONIZE_CACHE
:
memset
(
buff
,
0
,
bufflen
);
break
;
default:
#if 0
printk(KERN_INFO "scsi_debug: Unsupported command, "
...
...
@@ -394,7 +399,7 @@ int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, done_funct_t done)
return
schedule_resp
(
SCpnt
,
devip
,
done
,
errsts
,
scsi_debug_delay
);
}
static
int
scsi_debug_ioctl
(
Scsi_D
evice
*
dev
,
int
cmd
,
void
*
arg
)
static
int
scsi_debug_ioctl
(
struct
scsi_d
evice
*
dev
,
int
cmd
,
void
*
arg
)
{
if
(
SCSI_DEBUG_OPT_NOISE
&
scsi_debug_opts
)
{
printk
(
KERN_INFO
"scsi_debug: ioctl: cmd=0x%x
\n
"
,
cmd
);
...
...
@@ -403,7 +408,7 @@ static int scsi_debug_ioctl(Scsi_Device *dev, int cmd, void *arg)
/* return -ENOTTY; // correct return but upsets fdisk */
}
static
int
check_reset
(
Scsi_C
mnd
*
SCpnt
,
struct
sdebug_dev_info
*
devip
)
static
int
check_reset
(
struct
scsi_c
mnd
*
SCpnt
,
struct
sdebug_dev_info
*
devip
)
{
if
(
devip
->
reset
)
{
devip
->
reset
=
0
;
...
...
@@ -474,8 +479,8 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff,
int
dev_id_num
,
len
;
char
dev_id_str
[
6
];
dev_id_num
=
((
devip
->
host
->
host_no
+
1
)
*
1000
)
+
devip
->
target
;
dev_id_num
=
((
devip
->
host
->
host_no
+
1
)
*
2000
)
+
(
devip
->
target
*
1000
)
+
devip
->
lun
;
len
=
snprintf
(
dev_id_str
,
6
,
"%d"
,
dev_id_num
);
len
=
(
len
>
6
)
?
6
:
len
;
if
(
0
==
cmd
[
2
])
{
/* supported vital product data pages */
...
...
@@ -501,7 +506,7 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff,
}
/* drops through here for a standard inquiry */
arr
[
1
]
=
DEV_REMOVEABLE
(
target
)
?
0x80
:
0
;
/* Removable disk */
arr
[
2
]
=
3
;
/* claim SCSI 3 */
arr
[
2
]
=
scsi_debug_scsi_level
;
arr
[
4
]
=
SDEBUG_LONG_INQ_SZ
-
5
;
arr
[
7
]
=
0x3a
;
/* claim: WBUS16, SYNC, LINKED + CMDQUE */
memcpy
(
&
arr
[
8
],
vendor_id
,
8
);
...
...
@@ -643,6 +648,7 @@ static int resp_mode_sense(unsigned char * cmd, int target,
case
0x3f
:
/* Read all Mode pages */
len
=
resp_err_recov_pg
(
ap
,
pcontrol
,
target
);
len
+=
resp_disconnect_pg
(
ap
+
len
,
pcontrol
,
target
);
len
+=
resp_format_pg
(
ap
+
len
,
pcontrol
,
target
);
len
+=
resp_caching_pg
(
ap
+
len
,
pcontrol
,
target
);
len
+=
resp_ctrl_m_pg
(
ap
+
len
,
pcontrol
,
target
);
offset
+=
len
;
...
...
@@ -662,8 +668,8 @@ static int resp_mode_sense(unsigned char * cmd, int target,
return
0
;
}
static
int
resp_read
(
Scsi_Cmnd
*
SCpnt
,
int
upper_blk
,
int
block
,
int
num
,
struct
sdebug_dev_info
*
devip
)
static
int
resp_read
(
struct
scsi_cmnd
*
SCpnt
,
int
upper_blk
,
int
block
,
int
num
,
struct
sdebug_dev_info
*
devip
)
{
unsigned
char
*
buff
=
(
unsigned
char
*
)
SCpnt
->
request_buffer
;
int
nbytes
,
sgcount
;
...
...
@@ -711,8 +717,8 @@ static int resp_read(Scsi_Cmnd * SCpnt, int upper_blk, int block, int num,
return
0
;
}
static
int
resp_write
(
Scsi_Cmnd
*
SCpnt
,
int
upper_blk
,
int
block
,
int
num
,
struct
sdebug_dev_info
*
devip
)
static
int
resp_write
(
struct
scsi_cmnd
*
SCpnt
,
int
upper_blk
,
int
block
,
int
num
,
struct
sdebug_dev_info
*
devip
)
{
unsigned
char
*
buff
=
(
unsigned
char
*
)
SCpnt
->
request_buffer
;
int
nbytes
,
sgcount
;
...
...
@@ -756,8 +762,9 @@ static int resp_write(Scsi_Cmnd * SCpnt, int upper_blk, int block, int num,
static
int
resp_report_luns
(
unsigned
char
*
cmd
,
unsigned
char
*
buff
,
int
bufflen
,
struct
sdebug_dev_info
*
devip
)
{
unsigned
int
alloc_len
;
unsigned
int
alloc_len
,
lun_cnt
,
i
;
int
select_report
=
(
int
)
cmd
[
2
];
ScsiLun
*
one_lun
;
alloc_len
=
cmd
[
9
]
+
(
cmd
[
8
]
<<
8
)
+
(
cmd
[
7
]
<<
16
)
+
(
cmd
[
6
]
<<
24
);
if
((
alloc_len
<
16
)
||
(
select_report
>
2
))
{
...
...
@@ -765,8 +772,13 @@ static int resp_report_luns(unsigned char * cmd, unsigned char * buff,
return
(
COMMAND_COMPLETE
<<
8
)
|
(
CHECK_CONDITION
<<
1
);
}
if
(
bufflen
>
3
)
{
lun_cnt
=
min
((
int
)(
bufflen
/
sizeof
(
ScsiLun
)),
(
int
)
scsi_debug_max_luns
);
memset
(
buff
,
0
,
bufflen
);
buff
[
3
]
=
8
;
buff
[
3
]
=
8
*
lun_cnt
;
one_lun
=
(
ScsiLun
*
)
&
buff
[
0
];
for
(
i
=
0
;
i
<
lun_cnt
;
i
++
)
one_lun
[
i
].
scsi_lun
[
1
]
=
i
;
}
return
0
;
}
...
...
@@ -798,12 +810,13 @@ static void timer_intr_handler(unsigned long indx)
}
static
int
initialized
=
0
;
static
int
num_present
=
0
;
static
int
num_
hosts_
present
=
0
;
static
const
char
*
sdebug_proc_name
=
"scsi_debug"
;
static
int
scsi_debug_detect
(
Scsi_Host_Template
*
tpnt
)
static
int
scsi_debug_detect
(
struct
SHT
*
tpnt
)
{
int
k
,
sz
;
struct
Scsi_Host
*
hpnt
;
if
(
SCSI_DEBUG_OPT_NOISE
&
scsi_debug_opts
)
printk
(
KERN_INFO
"scsi_debug: detect
\n
"
);
...
...
@@ -813,7 +826,7 @@ static int scsi_debug_detect(Scsi_Host_Template * tpnt)
devInfop
=
vmalloc
(
sz
);
if
(
NULL
==
devInfop
)
{
printk
(
KERN_ERR
"scsi_debug_detect: out of "
"memory
, 0.5
\n
"
);
"memory
\n
"
);
return
0
;
}
memset
(
devInfop
,
0
,
sz
);
...
...
@@ -821,28 +834,31 @@ static int scsi_debug_detect(Scsi_Host_Template * tpnt)
fake_storep
=
vmalloc
(
sz
);
if
(
NULL
==
fake_storep
)
{
printk
(
KERN_ERR
"scsi_debug_detect: out of memory"
",
0
\n
"
);
",
1
\n
"
);
return
0
;
}
memset
(
fake_storep
,
0
,
sz
);
init_all_queued
();
tpnt
->
proc_name
=
(
char
*
)
sdebug_proc_name
;
for
(
num_present
=
0
,
k
=
0
;
k
<
NR_HOSTS_PRESENT
;
k
++
)
{
if
(
NULL
==
scsi_register
(
tpnt
,
0
))
printk
(
KERN_ERR
"scsi_debug_detect: "
"scsi_register failed k=%d
\n
"
,
k
);
else
++
num_present
;
}
#ifdef DRIVERFS_SUPPORT
if
(
num_present
)
{
sdebug_driverfs_driver
.
name
=
(
char
*
)
sdebug_proc_name
;
sdebug_driverfs_driver
.
bus
=
&
scsi_driverfs_bus_type
;
driver_register
(
&
sdebug_driverfs_driver
);
do_create_driverfs_files
();
}
#endif
return
num_present
;
tpnt
->
proc_name
=
(
char
*
)
sdebug_proc_name
;
for
(
num_hosts_present
=
0
,
k
=
0
;
k
<
NR_HOSTS_PRESENT
;
k
++
)
{
if
((
hpnt
=
scsi_register
(
tpnt
,
0
))
==
NULL
)
printk
(
KERN_ERR
"scsi_debug_detect: "
"scsi_register failed k=%d
\n
"
,
k
);
else
{
hpnt
->
max_lun
=
scsi_debug_max_luns
;
++
num_hosts_present
;
}
}
if
(
SCSI_DEBUG_OPT_NOISE
&
scsi_debug_opts
)
printk
(
KERN_INFO
"scsi_debug: ... built %d host(s)
\n
"
,
num_hosts_present
);
return
num_hosts_present
;
}
else
{
printk
(
KERN_WARNING
"scsi_debug_detect: called again
\n
"
);
return
0
;
...
...
@@ -854,11 +870,15 @@ static int num_releases = 0;
static
int
scsi_debug_release
(
struct
Scsi_Host
*
hpnt
)
{
int
host_no
=
hpnt
->
host_no
;
if
(
++
num_releases
==
num_hosts_present
)
{
if
(
SCSI_DEBUG_OPT_NOISE
&
scsi_debug_opts
)
printk
(
KERN_INFO
"scsi_debug: release
\n
"
);
printk
(
KERN_INFO
"scsi_debug: [last] release, "
"host_no=%u
\n
"
,
host_no
);
num_releases
=
0
;
initialized
=
0
;
stop_all_queued
();
scsi_unregister
(
hpnt
);
if
(
++
num_releases
==
num_present
)
{
#ifdef DRIVERFS_SUPPORT
do_remove_driverfs_files
();
driver_unregister
(
&
sdebug_driverfs_driver
);
...
...
@@ -866,14 +886,65 @@ static int scsi_debug_release(struct Scsi_Host * hpnt)
vfree
(
fake_storep
);
vfree
(
devInfop
);
}
else
{
if
(
SCSI_DEBUG_OPT_NOISE
&
scsi_debug_opts
)
printk
(
KERN_INFO
"scsi_debug: release, host_no=%u
\n
"
,
host_no
);
}
scsi_unregister
(
hpnt
);
return
0
;
}
static
struct
sdebug_dev_info
*
devInfoReg
(
Scsi_Cmnd
*
scmd
)
static
int
scsi_debug_slave_attach
(
struct
scsi_device
*
sdp
)
{
int
k
;
struct
sdebug_dev_info
*
devip
;
if
(
SCSI_DEBUG_OPT_NOISE
&
scsi_debug_opts
)
printk
(
KERN_INFO
"scsi_debug: slave_attach <%u %u %u %u>
\n
"
,
sdp
->
host
->
host_no
,
sdp
->
channel
,
sdp
->
id
,
sdp
->
lun
);
if
(
sdp
->
host
->
max_cmd_len
!=
SCSI_DEBUG_MAX_CMD_LEN
)
sdp
->
host
->
max_cmd_len
=
SCSI_DEBUG_MAX_CMD_LEN
;
for
(
k
=
0
;
k
<
scsi_debug_num_devs
;
++
k
)
{
devip
=
&
devInfop
[
k
];
if
((
devip
->
channel
==
sdp
->
channel
)
&&
(
devip
->
target
==
sdp
->
id
)
&&
(
devip
->
lun
==
sdp
->
lun
)
&&
(
devip
->
host
==
sdp
->
host
))
{
sdp
->
hostdata
=
devip
;
break
;
}
}
if
(
sdp
->
host
->
cmd_per_lun
)
scsi_adjust_queue_depth
(
sdp
,
SDEBUG_TAGGED_QUEUING
,
sdp
->
host
->
cmd_per_lun
);
return
0
;
}
static
void
scsi_debug_slave_detach
(
struct
scsi_device
*
sdp
)
{
struct
sdebug_dev_info
*
devip
=
(
struct
sdebug_dev_info
*
)
sdp
->
hostdata
;
if
(
SCSI_DEBUG_OPT_NOISE
&
scsi_debug_opts
)
printk
(
KERN_INFO
"scsi_debug: slave_detach <%u %u %u %u>
\n
"
,
sdp
->
host
->
host_no
,
sdp
->
channel
,
sdp
->
id
,
sdp
->
lun
);
if
(
devip
)
{
/* make this slot avaliable for re-use */
memset
(
devip
,
0
,
sizeof
(
struct
sdebug_dev_info
));
sdp
->
hostdata
=
NULL
;
}
}
static
struct
sdebug_dev_info
*
devInfoReg
(
struct
scsi_cmnd
*
scmd
)
{
int
k
;
struct
scsi_device
*
sdp
=
scmd
->
device
;
struct
sdebug_dev_info
*
devip
=
(
struct
sdebug_dev_info
*
)
sdp
->
hostdata
;
if
(
devip
)
return
devip
;
for
(
k
=
0
;
k
<
scsi_debug_num_devs
;
++
k
)
{
devip
=
&
devInfop
[
k
];
if
((
devip
->
channel
==
scmd
->
channel
)
&&
...
...
@@ -915,7 +986,7 @@ static void mk_sense_buffer(struct sdebug_dev_info * devip, int key,
sbuff
[
13
]
=
asq
;
}
static
int
scsi_debug_abort
(
Scsi_C
mnd
*
SCpnt
)
static
int
scsi_debug_abort
(
struct
scsi_c
mnd
*
SCpnt
)
{
if
(
SCSI_DEBUG_OPT_NOISE
&
scsi_debug_opts
)
printk
(
KERN_INFO
"scsi_debug: abort
\n
"
);
...
...
@@ -938,7 +1009,7 @@ static int scsi_debug_biosparam(struct scsi_device *sdev,
return
0
;
}
static
int
scsi_debug_device_reset
(
Scsi_C
mnd
*
SCpnt
)
static
int
scsi_debug_device_reset
(
struct
scsi_c
mnd
*
SCpnt
)
{
struct
sdebug_dev_info
*
devip
;
...
...
@@ -953,9 +1024,9 @@ static int scsi_debug_device_reset(Scsi_Cmnd * SCpnt)
return
SUCCESS
;
}
static
int
scsi_debug_bus_reset
(
Scsi_C
mnd
*
SCpnt
)
static
int
scsi_debug_bus_reset
(
struct
scsi_c
mnd
*
SCpnt
)
{
Scsi_D
evice
*
sdp
;
struct
scsi_d
evice
*
sdp
;
struct
Scsi_Host
*
hp
;
int
k
;
...
...
@@ -971,7 +1042,7 @@ static int scsi_debug_bus_reset(Scsi_Cmnd * SCpnt)
return
SUCCESS
;
}
static
int
scsi_debug_host_reset
(
Scsi_C
mnd
*
SCpnt
)
static
int
scsi_debug_host_reset
(
struct
scsi_c
mnd
*
SCpnt
)
{
int
k
;
...
...
@@ -1048,11 +1119,18 @@ static int schedule_resp(struct scsi_cmnd * cmnd,
{
int
k
,
num
;
if
(
SCSI_DEBUG_OPT_NOISE
&
scsi_debug_opts
)
{
if
(
(
SCSI_DEBUG_OPT_NOISE
&
scsi_debug_opts
)
&&
cmnd
)
{
printk
(
KERN_INFO
"scsi_debug: cmd "
);
for
(
k
=
0
,
num
=
cmnd
->
cmd_len
;
k
<
num
;
++
k
)
printk
(
"%02x "
,
(
int
)
cmnd
->
cmnd
[
k
]);
printk
(
"result=0x%x
\n
"
,
scsi_result
);
printk
(
"
\n
"
);
if
(
scsi_result
)
{
struct
scsi_device
*
sdp
=
cmnd
->
device
;
printk
(
KERN_INFO
"scsi_debug: ... <%u %u %u %u> "
"non-zero result=0x%x
\n
"
,
sdp
->
host
->
host_no
,
sdp
->
channel
,
sdp
->
id
,
sdp
->
lun
,
scsi_result
);
}
}
if
(
cmnd
&&
devip
)
{
/* simulate autosense by this driver */
...
...
@@ -1113,6 +1191,38 @@ static int __init num_devs_setup(char *str)
}
__setup
(
"scsi_debug_num_devs="
,
num_devs_setup
);
static
int
__init
max_luns_setup
(
char
*
str
)
{
int
tmp
;
if
(
get_option
(
&
str
,
&
tmp
)
==
1
)
{
if
(
tmp
>
0
)
scsi_debug_max_luns
=
tmp
;
return
1
;
}
else
{
printk
(
KERN_INFO
"scsi_debug_max_luns: usage scsi_debug_max_luns=<n> "
"(<n> is a postive integer (def=2))
\n
"
);
return
0
;
}
}
__setup
(
"scsi_debug_max_luns="
,
max_luns_setup
);
static
int
__init
scsi_level_setup
(
char
*
str
)
{
int
tmp
;
if
(
get_option
(
&
str
,
&
tmp
)
==
1
)
{
if
(
tmp
>
0
)
scsi_debug_scsi_level
=
tmp
;
return
1
;
}
else
{
printk
(
KERN_INFO
"scsi_debug_scsi_level: usage "
"scsi_debug_scsi_level=<n> (<n> is 1..4 (def=3))
\n
"
);
return
0
;
}
}
__setup
(
"scsi_debug_scsi_level="
,
scsi_level_setup
);
static
int
__init
dev_size_mb_setup
(
char
*
str
)
{
int
tmp
;
...
...
@@ -1186,6 +1296,10 @@ MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
MODULE_DESCRIPTION
(
"SCSI debug adapter driver"
);
MODULE_PARM
(
scsi_debug_num_devs
,
"i"
);
MODULE_PARM_DESC
(
scsi_debug_num_devs
,
"number of SCSI devices to simulate"
);
MODULE_PARM
(
scsi_debug_max_luns
,
"i"
);
MODULE_PARM_DESC
(
scsi_debug_max_luns
,
"number of SCSI LUNs per target to simulate"
);
MODULE_PARM
(
scsi_debug_scsi_level
,
"i"
);
MODULE_PARM_DESC
(
scsi_debug_scsi_level
,
"SCSI level to simulate"
);
MODULE_PARM
(
scsi_debug_dev_size_mb
,
"i"
);
MODULE_PARM_DESC
(
scsi_debug_dev_size_mb
,
"size in MB of ram shared by devs"
);
MODULE_PARM
(
scsi_debug_opts
,
"i"
);
...
...
@@ -1237,13 +1351,15 @@ static int scsi_debug_proc_info(char *buffer, char **start, off_t offset,
pos
=
len
=
sprintf
(
buffer
,
"scsi_debug adapter driver, %s
\n
"
"num_devs=%d, shared (ram) size=%d MB, opts=0x%x, "
"every_nth=%d(curr:%d)
\n
"
"sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d, "
"delay=%d
\n
number of aborts=%d, device_reset=%d, bus_resets=%d, "
"delay=%d, max_luns=%d, scsi_level=%d
\n
"
"sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d
\n
"
"number of aborts=%d, device_reset=%d, bus_resets=%d, "
"host_resets=%d
\n
"
,
scsi_debug_version_str
,
scsi_debug_num_devs
,
scsi_debug_dev_size_mb
,
scsi_debug_opts
,
scsi_debug_every_nth
,
scsi_debug_cmnd_count
,
SECT_SIZE
,
N_CYLINDER
,
N_HEAD
,
N_SECTOR
,
scsi_debug_delay
,
scsi_debug_cmnd_count
,
scsi_debug_delay
,
scsi_debug_max_luns
,
scsi_debug_scsi_level
,
SECT_SIZE
,
N_CYLINDER
,
N_HEAD
,
N_SECTOR
,
num_aborts
,
num_dev_resets
,
num_bus_resets
,
num_host_resets
);
if
(
pos
<
offset
)
{
len
=
0
;
...
...
@@ -1253,8 +1369,7 @@ static int scsi_debug_proc_info(char *buffer, char **start, off_t offset,
len
-=
(
offset
-
begin
);
if
(
len
>
length
)
len
=
length
;
return
(
len
);
return
len
;
}
#ifdef DRIVERFS_SUPPORT
...
...
@@ -1280,7 +1395,6 @@ static ssize_t sdebug_delay_write(struct device_driver * ddp,
}
return
-
EINVAL
;
}
DRIVER_ATTR
(
delay
,
S_IRUGO
|
S_IWUSR
,
sdebug_delay_read
,
sdebug_delay_write
)
...
...
@@ -1312,7 +1426,6 @@ static ssize_t sdebug_opts_write(struct device_driver * ddp,
scsi_debug_opts
=
opts
;
return
count
;
}
DRIVER_ATTR
(
opts
,
S_IRUGO
|
S_IWUSR
,
sdebug_opts_read
,
sdebug_opts_write
)
...
...
@@ -1321,18 +1434,53 @@ static ssize_t sdebug_num_devs_read(struct device_driver * ddp, char * buf,
{
return
off
?
0
:
snprintf
(
buf
,
count
,
"%d
\n
"
,
scsi_debug_num_devs
);
}
DRIVER_ATTR
(
num_devs
,
S_IRUGO
,
sdebug_num_devs_read
,
NULL
)
static
ssize_t
sdebug_dev_size_mb_read
(
struct
device_driver
*
ddp
,
char
*
buf
,
size_t
count
,
loff_t
off
)
{
return
off
?
0
:
snprintf
(
buf
,
count
,
"%d
\n
"
,
scsi_debug_dev_size_mb
);
}
DRIVER_ATTR
(
dev_size_mb
,
S_IRUGO
,
sdebug_dev_size_mb_read
,
NULL
)
static
ssize_t
sdebug_every_nth_read
(
struct
device_driver
*
ddp
,
char
*
buf
,
size_t
count
,
loff_t
off
)
{
return
off
?
0
:
snprintf
(
buf
,
count
,
"%d
\n
"
,
scsi_debug_every_nth
);
}
DRIVER_ATTR
(
every_nth
,
S_IRUGO
,
sdebug_every_nth_read
,
NULL
)
static
ssize_t
sdebug_max_luns_read
(
struct
device_driver
*
ddp
,
char
*
buf
,
size_t
count
,
loff_t
off
)
{
return
off
?
0
:
snprintf
(
buf
,
count
,
"%d
\n
"
,
scsi_debug_max_luns
);
}
DRIVER_ATTR
(
max_luns
,
S_IRUGO
,
sdebug_max_luns_read
,
NULL
)
static
ssize_t
sdebug_scsi_level_read
(
struct
device_driver
*
ddp
,
char
*
buf
,
size_t
count
,
loff_t
off
)
{
return
off
?
0
:
snprintf
(
buf
,
count
,
"%d
\n
"
,
scsi_debug_scsi_level
);
}
DRIVER_ATTR
(
scsi_level
,
S_IRUGO
,
sdebug_scsi_level_read
,
NULL
)
static
void
do_create_driverfs_files
()
{
driver_create_file
(
&
sdebug_driverfs_driver
,
&
driver_attr_delay
);
driver_create_file
(
&
sdebug_driverfs_driver
,
&
driver_attr_opts
);
driver_create_file
(
&
sdebug_driverfs_driver
,
&
driver_attr_num_devs
);
driver_create_file
(
&
sdebug_driverfs_driver
,
&
driver_attr_dev_size_mb
);
driver_create_file
(
&
sdebug_driverfs_driver
,
&
driver_attr_every_nth
);
driver_create_file
(
&
sdebug_driverfs_driver
,
&
driver_attr_max_luns
);
driver_create_file
(
&
sdebug_driverfs_driver
,
&
driver_attr_scsi_level
);
}
static
void
do_remove_driverfs_files
()
{
driver_remove_file
(
&
sdebug_driverfs_driver
,
&
driver_attr_scsi_level
);
driver_remove_file
(
&
sdebug_driverfs_driver
,
&
driver_attr_max_luns
);
driver_remove_file
(
&
sdebug_driverfs_driver
,
&
driver_attr_every_nth
);
driver_remove_file
(
&
sdebug_driverfs_driver
,
&
driver_attr_dev_size_mb
);
driver_remove_file
(
&
sdebug_driverfs_driver
,
&
driver_attr_num_devs
);
driver_remove_file
(
&
sdebug_driverfs_driver
,
&
driver_attr_opts
);
driver_remove_file
(
&
sdebug_driverfs_driver
,
&
driver_attr_delay
);
...
...
drivers/scsi/scsi_debug.h
View file @
49ce412f
...
...
@@ -3,17 +3,20 @@
#include <linux/types.h>
#include <linux/kdev_t.h>
static
int
scsi_debug_detect
(
Scsi_Host_Template
*
);
static
int
scsi_debug_detect
(
struct
SHT
*
);
static
int
scsi_debug_slave_attach
(
struct
scsi_device
*
);
static
void
scsi_debug_slave_detach
(
struct
scsi_device
*
);
static
int
scsi_debug_release
(
struct
Scsi_Host
*
);
/* static int scsi_debug_command(Scsi_Cmnd *); */
static
int
scsi_debug_queuecommand
(
Scsi_Cmnd
*
,
void
(
*
done
)
(
Scsi_Cmnd
*
));
static
int
scsi_debug_ioctl
(
Scsi_Device
*
,
int
,
void
*
);
/* static int scsi_debug_command(struct scsi_cmnd *); */
static
int
scsi_debug_queuecommand
(
struct
scsi_cmnd
*
,
void
(
*
done
)
(
struct
scsi_cmnd
*
));
static
int
scsi_debug_ioctl
(
struct
scsi_device
*
,
int
,
void
*
);
static
int
scsi_debug_biosparam
(
struct
scsi_device
*
,
struct
block_device
*
,
sector_t
,
int
[]);
static
int
scsi_debug_abort
(
Scsi_C
mnd
*
);
static
int
scsi_debug_bus_reset
(
Scsi_C
mnd
*
);
static
int
scsi_debug_device_reset
(
Scsi_C
mnd
*
);
static
int
scsi_debug_host_reset
(
Scsi_C
mnd
*
);
static
int
scsi_debug_abort
(
struct
scsi_c
mnd
*
);
static
int
scsi_debug_bus_reset
(
struct
scsi_c
mnd
*
);
static
int
scsi_debug_device_reset
(
struct
scsi_c
mnd
*
);
static
int
scsi_debug_host_reset
(
struct
scsi_c
mnd
*
);
static
int
scsi_debug_proc_info
(
char
*
,
char
**
,
off_t
,
int
,
int
,
int
);
static
const
char
*
scsi_debug_info
(
struct
Scsi_Host
*
);
...
...
@@ -33,6 +36,8 @@ static Scsi_Host_Template driver_template = {
.
name
=
"SCSI DEBUG"
,
.
info
=
scsi_debug_info
,
.
detect
=
scsi_debug_detect
,
.
slave_attach
=
scsi_debug_slave_attach
,
.
slave_detach
=
scsi_debug_slave_detach
,
.
release
=
scsi_debug_release
,
.
ioctl
=
scsi_debug_ioctl
,
.
queuecommand
=
scsi_debug_queuecommand
,
...
...
drivers/scsi/scsi_mid_low_api.txt
View file @
49ce412f
...
...
@@ -352,34 +352,12 @@ int proc_info(char * buffer, char ** start, off_t offset,
* Locks: lock_kernel() active on entry and expected to be active
* on return.
*
* Notes: Invoked from mid level's scsi_unregister_host(). When a
* host is being unregistered the mid level does not bother to
* call revoke() on the devices it controls.
* Notes: Invoked from mid level's scsi_unregister_host().
* This function should call scsi_unregister(shp) [found in hosts.c]
* prior to returning.
**/
int release(struct Scsi_Host * shp);
/**
* revoke - indicate disinterest in a scsi device
* @sdp: host template for this driver.
*
* Return value ignored.
*
* Required: no
*
* Locks: none held
*
* Notes: Called when "scsi remove-single-device <h> <b> <t> <l>"
* is written to /proc/scsi/scsi to indicate the device is no longer
* required. It is called after the upper level drivers have detached
* this device and before the device name (e.g. /dev/sdc) is
* unregistered and the resources associated with it are freed.
**/
int revoke(Scsi_device * sdp);
/**
* select_queue_depths - calculate allowable number of scsi commands
* that can be queued on each device (disk)
...
...
drivers/scsi/scsi_scan.c
View file @
49ce412f
...
...
@@ -1322,7 +1322,6 @@ static int scsi_add_lun(Scsi_Device *sdevscan, Scsi_Device **sdevnew,
Scsi_Request
*
sreq
,
char
*
inq_result
,
int
*
bflags
)
{
Scsi_Device
*
sdev
;
struct
Scsi_Device_Template
*
sdt
;
char
devname
[
64
];
extern
devfs_handle_t
scsi_devfs_handle
;
...
...
@@ -1479,18 +1478,7 @@ static int scsi_add_lun(Scsi_Device *sdevscan, Scsi_Device **sdevnew,
* function */
sdev
->
max_device_blocked
=
SCSI_DEFAULT_DEVICE_BLOCKED
;
for
(
sdt
=
scsi_devicelist
;
sdt
;
sdt
=
sdt
->
next
)
if
(
sdt
->
detect
)
sdev
->
attached
+=
(
*
sdt
->
detect
)
(
sdev
);
if
(
sdev
->
host
->
hostt
->
slave_attach
!=
NULL
)
{
if
(
sdev
->
host
->
hostt
->
slave_attach
(
sdev
)
!=
0
)
{
printk
(
KERN_INFO
"%s: scsi_add_lun: failed low level driver attach, setting device offline"
,
devname
);
sdev
->
online
=
FALSE
;
}
}
else
if
(
sdev
->
host
->
cmd_per_lun
)
{
scsi_adjust_queue_depth
(
sdev
,
0
,
sdev
->
host
->
cmd_per_lun
);
}
scsi_detect_device
(
sdev
);
if
(
sdevnew
!=
NULL
)
*
sdevnew
=
sdev
;
...
...
@@ -2010,7 +1998,6 @@ static void scsi_scan_selected_lun(struct Scsi_Host *shost, uint channel,
uint
id
,
uint
lun
)
{
Scsi_Device
*
sdevscan
,
*
sdev
=
NULL
;
struct
Scsi_Device_Template
*
sdt
;
int
res
;
if
((
channel
>
shost
->
max_channel
)
||
(
id
>=
shost
->
max_id
)
||
...
...
@@ -2028,24 +2015,7 @@ static void scsi_scan_selected_lun(struct Scsi_Host *shost, uint channel,
if
(
res
!=
SCSI_SCAN_LUN_PRESENT
)
return
;
BUG_ON
(
sdev
==
NULL
);
scsi_build_commandblocks
(
sdev
);
if
(
sdev
->
current_queue_depth
==
0
)
{
printk
(
ALLOC_FAILURE_MSG
,
__FUNCTION__
);
return
;
}
for
(
sdt
=
scsi_devicelist
;
sdt
;
sdt
=
sdt
->
next
)
if
(
sdt
->
init
&&
sdt
->
dev_noticed
)
(
*
sdt
->
init
)
();
for
(
sdt
=
scsi_devicelist
;
sdt
;
sdt
=
sdt
->
next
)
if
(
sdt
->
attach
)
(
*
sdt
->
attach
)
(
sdev
);
if
(
!
sdev
->
attached
)
scsi_release_commandblocks
(
sdev
);
scsi_attach_device
(
sdev
);
}
/**
...
...
drivers/scsi/scsi_syms.c
View file @
49ce412f
...
...
@@ -32,6 +32,8 @@ EXPORT_SYMBOL(scsi_register_device);
EXPORT_SYMBOL
(
scsi_unregister_device
);
EXPORT_SYMBOL
(
scsi_register_host
);
EXPORT_SYMBOL
(
scsi_unregister_host
);
EXPORT_SYMBOL
(
scsi_add_host
);
EXPORT_SYMBOL
(
scsi_remove_host
);
EXPORT_SYMBOL
(
scsi_register
);
EXPORT_SYMBOL
(
scsi_unregister
);
EXPORT_SYMBOL
(
scsicam_bios_param
);
...
...
@@ -80,6 +82,8 @@ EXPORT_SYMBOL(scsi_end_request);
EXPORT_SYMBOL
(
scsi_register_blocked_host
);
EXPORT_SYMBOL
(
scsi_deregister_blocked_host
);
EXPORT_SYMBOL
(
scsi_slave_attach
);
EXPORT_SYMBOL
(
scsi_slave_detach
);
/*
* This symbol is for the highlevel drivers (e.g. sg) only.
...
...
@@ -92,7 +96,6 @@ EXPORT_SYMBOL(scsi_reset_provider);
EXPORT_SYMBOL
(
scsi_host_get_next
);
EXPORT_SYMBOL
(
scsi_host_hn_get
);
EXPORT_SYMBOL
(
scsi_host_put
);
EXPORT_SYMBOL
(
scsi_devicelist
);
EXPORT_SYMBOL
(
scsi_device_types
);
/*
...
...
drivers/scsi/sd.c
View file @
49ce412f
...
...
@@ -83,6 +83,7 @@ struct scsi_disk {
unsigned
RCD
:
1
;
/* state of disk RCD bit */
};
static
int
sd_nr_dev
;
/* XXX(hch) bad hack, we want a bitmap instead */
static
LIST_HEAD
(
sd_devlist
);
static
spinlock_t
sd_devlist_lock
=
SPIN_LOCK_UNLOCKED
;
...
...
@@ -106,7 +107,6 @@ static struct Scsi_Device_Template sd_template = {
.
name
=
"disk"
,
.
tag
=
"sd"
,
.
scsi_type
=
TYPE_DISK
,
.
blk
=
1
,
.
detect
=
sd_detect
,
.
attach
=
sd_attach
,
.
detach
=
sd_detach
,
...
...
@@ -1179,7 +1179,6 @@ static int sd_detect(struct scsi_device * sdp)
SCSI_LOG_HLQUEUE
(
3
,
printk
(
"sd_detect: type=%d
\n
"
,
sdp
->
type
));
if
(
sdp
->
type
!=
TYPE_DISK
&&
sdp
->
type
!=
TYPE_MOD
)
return
0
;
sd_template
.
dev_noticed
++
;
return
1
;
}
...
...
@@ -1213,9 +1212,12 @@ static int sd_attach(struct scsi_device * sdp)
SCSI_LOG_HLQUEUE
(
3
,
printk
(
"sd_attach: scsi device: <%d,%d,%d,%d>
\n
"
,
sdp
->
host
->
host_no
,
sdp
->
channel
,
sdp
->
id
,
sdp
->
lun
));
if
(
scsi_slave_attach
(
sdp
))
goto
out
;
sdkp
=
kmalloc
(
sizeof
(
*
sdkp
),
GFP_KERNEL
);
if
(
!
sdkp
)
goto
out
;
goto
out
_detach
;
gd
=
alloc_disk
(
16
);
if
(
!
gd
)
...
...
@@ -1228,7 +1230,7 @@ static int sd_attach(struct scsi_device * sdp)
* XXX use find_first_zero_bit on it. This will happen at the
* XXX same time template->nr_* goes away. --hch
*/
dsk_nr
=
sd_
template
.
nr_dev
++
;
dsk_nr
=
sd_nr_dev
++
;
sdkp
->
device
=
sdp
;
sdkp
->
driver
=
&
sd_template
;
...
...
@@ -1264,8 +1266,9 @@ static int sd_attach(struct scsi_device * sdp)
out_free:
kfree
(
sdkp
);
out_detach:
scsi_slave_detach
(
sdp
);
out:
sdp
->
attached
--
;
return
1
;
}
...
...
@@ -1313,9 +1316,8 @@ static void sd_detach(struct scsi_device * sdp)
sd_devlist_remove
(
sdkp
);
del_gendisk
(
sdkp
->
disk
);
sdp
->
attached
--
;
sd_template
.
dev_noticed
--
;
sd_template
.
nr_dev
--
;
scsi_slave_detach
(
sdp
);
sd_nr_dev
--
;
put_disk
(
sdkp
->
disk
);
kfree
(
sdkp
);
}
...
...
drivers/scsi/sg.c
View file @
49ce412f
...
...
@@ -110,7 +110,6 @@ static int sg_allow_dio = SG_ALLOW_DIO_DEF;
#define SG_DEV_ARR_LUMP 6
/* amount to over allocate sg_dev_arr by */
static
int
sg_init
(
void
);
static
int
sg_attach
(
Scsi_Device
*
);
static
int
sg_detect
(
Scsi_Device
*
);
static
void
sg_detach
(
Scsi_Device
*
);
...
...
@@ -126,7 +125,6 @@ static struct Scsi_Device_Template sg_template = {
.
tag
=
"sg"
,
.
scsi_type
=
0xff
,
.
detect
=
sg_detect
,
.
init
=
sg_init
,
.
attach
=
sg_attach
,
.
detach
=
sg_detach
};
...
...
@@ -235,6 +233,9 @@ static int sg_last_dev(void);
#endif
static
Sg_device
**
sg_dev_arr
=
NULL
;
static
int
sg_dev_noticed
;
static
int
sg_dev_max
;
static
int
sg_nr_dev
;
#define SZ_SG_HEADER sizeof(struct sg_header)
#define SZ_SG_IO_HDR sizeof(sg_io_hdr_t)
...
...
@@ -1340,59 +1341,10 @@ static struct file_operations sg_fops = {
static
int
sg_detect
(
Scsi_Device
*
scsidp
)
{
sg_
template
.
dev_noticed
++
;
sg_dev_noticed
++
;
return
1
;
}
/* Driver initialization */
static
int
sg_init
()
{
static
int
sg_registered
=
0
;
unsigned
long
iflags
;
int
tmp_dev_max
;
Sg_device
**
tmp_da
;
if
((
sg_template
.
dev_noticed
==
0
)
||
sg_dev_arr
)
return
0
;
SCSI_LOG_TIMEOUT
(
3
,
printk
(
"sg_init
\n
"
));
write_lock_irqsave
(
&
sg_dev_arr_lock
,
iflags
);
tmp_dev_max
=
sg_template
.
dev_noticed
+
SG_DEV_ARR_LUMP
;
write_unlock_irqrestore
(
&
sg_dev_arr_lock
,
iflags
);
tmp_da
=
(
Sg_device
**
)
vmalloc
(
tmp_dev_max
*
sizeof
(
Sg_device
*
));
if
(
NULL
==
tmp_da
)
{
printk
(
KERN_ERR
"sg_init: no space for sg_dev_arr
\n
"
);
return
1
;
}
write_lock_irqsave
(
&
sg_dev_arr_lock
,
iflags
);
if
(
!
sg_registered
)
{
if
(
register_chrdev
(
SCSI_GENERIC_MAJOR
,
"sg"
,
&
sg_fops
))
{
printk
(
KERN_ERR
"Unable to get major %d for generic SCSI device
\n
"
,
SCSI_GENERIC_MAJOR
);
write_unlock_irqrestore
(
&
sg_dev_arr_lock
,
iflags
);
vfree
((
char
*
)
tmp_da
);
return
1
;
}
sg_registered
++
;
}
memset
(
tmp_da
,
0
,
tmp_dev_max
*
sizeof
(
Sg_device
*
));
sg_template
.
dev_max
=
tmp_dev_max
;
sg_dev_arr
=
tmp_da
;
write_unlock_irqrestore
(
&
sg_dev_arr_lock
,
iflags
);
#ifdef CONFIG_PROC_FS
sg_proc_init
();
#endif
/* CONFIG_PROC_FS */
return
0
;
}
#ifndef MODULE
static
int
__init
sg_def_reserved_size_setup
(
char
*
str
)
...
...
@@ -1444,36 +1396,37 @@ sg_attach(Scsi_Device * scsidp)
if
(
!
disk
)
return
1
;
if
(
scsi_slave_attach
(
scsidp
))
return
1
;
write_lock_irqsave
(
&
sg_dev_arr_lock
,
iflags
);
if
(
sg_
template
.
nr_dev
>=
sg_template
.
dev_max
)
{
/* try to resize */
if
(
sg_
nr_dev
>=
sg_
dev_max
)
{
/* try to resize */
Sg_device
**
tmp_da
;
int
tmp_dev_max
=
sg_
template
.
nr_dev
+
SG_DEV_ARR_LUMP
;
int
tmp_dev_max
=
sg_nr_dev
+
SG_DEV_ARR_LUMP
;
write_unlock_irqrestore
(
&
sg_dev_arr_lock
,
iflags
);
tmp_da
=
(
Sg_device
**
)
vmalloc
(
tmp_dev_max
*
sizeof
(
Sg_device
*
));
if
(
NULL
==
tmp_da
)
{
scsidp
->
attached
--
;
printk
(
KERN_ERR
"sg_attach: device array cannot be resized
\n
"
);
put_disk
(
disk
);
scsi_slave_detach
(
scsidp
);
return
1
;
}
write_lock_irqsave
(
&
sg_dev_arr_lock
,
iflags
);
memset
(
tmp_da
,
0
,
tmp_dev_max
*
sizeof
(
Sg_device
*
));
memcpy
(
tmp_da
,
sg_dev_arr
,
sg_
template
.
dev_max
*
sizeof
(
Sg_device
*
));
sg_dev_max
*
sizeof
(
Sg_device
*
));
vfree
((
char
*
)
sg_dev_arr
);
sg_dev_arr
=
tmp_da
;
sg_
template
.
dev_max
=
tmp_dev_max
;
sg_dev_max
=
tmp_dev_max
;
}
find_empty_slot:
for
(
k
=
0
;
k
<
sg_
template
.
dev_max
;
k
++
)
for
(
k
=
0
;
k
<
sg_dev_max
;
k
++
)
if
(
!
sg_dev_arr
[
k
])
break
;
if
(
k
>
SG_MAX_DEVS_MASK
)
{
scsidp
->
attached
--
;
write_unlock_irqrestore
(
&
sg_dev_arr_lock
,
iflags
);
printk
(
KERN_WARNING
"Unable to attach sg device <%d, %d, %d, %d>"
...
...
@@ -1483,9 +1436,10 @@ sg_attach(Scsi_Device * scsidp)
if
(
NULL
!=
sdp
)
vfree
((
char
*
)
sdp
);
put_disk
(
disk
);
scsi_slave_detach
(
scsidp
);
return
1
;
}
if
(
k
<
sg_
template
.
dev_max
)
{
if
(
k
<
sg_dev_max
)
{
if
(
NULL
==
sdp
)
{
write_unlock_irqrestore
(
&
sg_dev_arr_lock
,
iflags
);
sdp
=
(
Sg_device
*
)
vmalloc
(
sizeof
(
Sg_device
));
...
...
@@ -1496,10 +1450,10 @@ sg_attach(Scsi_Device * scsidp)
}
else
sdp
=
NULL
;
if
(
NULL
==
sdp
)
{
scsidp
->
attached
--
;
write_unlock_irqrestore
(
&
sg_dev_arr_lock
,
iflags
);
printk
(
KERN_ERR
"sg_attach: Sg_device cannot be allocated
\n
"
);
put_disk
(
disk
);
scsi_slave_detach
(
scsidp
);
return
1
;
}
...
...
@@ -1527,7 +1481,7 @@ sg_attach(Scsi_Device * scsidp)
sdp
->
sg_driverfs_dev
.
parent
=
&
scsidp
->
sdev_driverfs_dev
;
sdp
->
sg_driverfs_dev
.
bus
=
&
scsi_driverfs_bus_type
;
sg_
template
.
nr_dev
++
;
sg_nr_dev
++
;
sg_dev_arr
[
k
]
=
sdp
;
write_unlock_irqrestore
(
&
sg_dev_arr_lock
,
iflags
);
...
...
@@ -1570,7 +1524,7 @@ sg_detach(Scsi_Device * scsidp)
return
;
delay
=
0
;
write_lock_irqsave
(
&
sg_dev_arr_lock
,
iflags
);
for
(
k
=
0
;
k
<
sg_
template
.
dev_max
;
k
++
)
{
for
(
k
=
0
;
k
<
sg_dev_max
;
k
++
)
{
sdp
=
sg_dev_arr
[
k
];
if
((
NULL
==
sdp
)
||
(
sdp
->
device
!=
scsidp
))
continue
;
/* dirty but lowers nesting */
...
...
@@ -1607,9 +1561,9 @@ sg_detach(Scsi_Device * scsidp)
SCSI_LOG_TIMEOUT
(
3
,
printk
(
"sg_detach: dev=%d
\n
"
,
k
));
sg_dev_arr
[
k
]
=
NULL
;
}
scsi
dp
->
attached
--
;
sg_
template
.
nr_dev
--
;
sg_
template
.
dev_noticed
--
;
/* from <dan@lectra.fr> */
scsi
_slave_detach
(
scsidp
)
;
sg_nr_dev
--
;
sg_dev_noticed
--
;
/* from <dan@lectra.fr> */
break
;
}
write_unlock_irqrestore
(
&
sg_dev_arr_lock
,
iflags
);
...
...
@@ -1643,9 +1597,21 @@ MODULE_PARM_DESC(def_reserved_size, "size of buffer reserved for each fd");
static
int
__init
init_sg
(
void
)
{
int
rc
;
if
(
def_reserved_size
>=
0
)
sg_big_buff
=
def_reserved_size
;
return
scsi_register_device
(
&
sg_template
);
rc
=
register_chrdev
(
SCSI_GENERIC_MAJOR
,
"sg"
,
&
sg_fops
);
if
(
rc
)
return
rc
;
rc
=
scsi_register_device
(
&
sg_template
);
if
(
rc
)
return
rc
;
#ifdef CONFIG_PROC_FS
sg_proc_init
();
#endif
/* CONFIG_PROC_FS */
return
0
;
}
static
void
__exit
...
...
@@ -1660,7 +1626,7 @@ exit_sg(void)
vfree
((
char
*
)
sg_dev_arr
);
sg_dev_arr
=
NULL
;
}
sg_
template
.
dev_max
=
0
;
sg_dev_max
=
0
;
}
static
int
...
...
@@ -2552,7 +2518,7 @@ sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp)
if
(
sdp
->
detached
&&
(
NULL
==
sdp
->
headfp
))
{
int
k
,
maxd
;
maxd
=
sg_
template
.
dev_max
;
maxd
=
sg_dev_max
;
for
(
k
=
0
;
k
<
maxd
;
++
k
)
{
if
(
sdp
==
sg_dev_arr
[
k
])
break
;
...
...
@@ -2684,7 +2650,7 @@ sg_last_dev()
unsigned
long
iflags
;
read_lock_irqsave
(
&
sg_dev_arr_lock
,
iflags
);
for
(
k
=
sg_
template
.
dev_max
-
1
;
k
>=
0
;
--
k
)
for
(
k
=
sg_dev_max
-
1
;
k
>=
0
;
--
k
)
if
(
sg_dev_arr
[
k
]
&&
sg_dev_arr
[
k
]
->
device
)
break
;
read_unlock_irqrestore
(
&
sg_dev_arr_lock
,
iflags
);
...
...
@@ -2700,7 +2666,7 @@ sg_get_dev(int dev)
if
(
sg_dev_arr
&&
(
dev
>=
0
))
{
read_lock_irqsave
(
&
sg_dev_arr_lock
,
iflags
);
if
(
dev
<
sg_
template
.
dev_max
)
if
(
dev
<
sg_dev_max
)
sdp
=
sg_dev_arr
[
dev
];
read_unlock_irqrestore
(
&
sg_dev_arr_lock
,
iflags
);
}
...
...
@@ -2982,7 +2948,7 @@ sg_proc_debug_info(char *buffer, int *len, off_t * begin,
}
max_dev
=
sg_last_dev
();
PRINT_PROC
(
"dev_max(currently)=%d max_active_device=%d (origin 1)
\n
"
,
sg_
template
.
dev_max
,
max_dev
);
sg_dev_max
,
max_dev
);
PRINT_PROC
(
" def_reserved_size=%d
\n
"
,
sg_big_buff
);
for
(
j
=
0
;
j
<
max_dev
;
++
j
)
{
if
((
sdp
=
sg_get_dev
(
j
)))
{
...
...
drivers/scsi/sr.c
View file @
49ce412f
...
...
@@ -65,11 +65,9 @@ MODULE_PARM(xa_test, "i"); /* see sr_ioctl.c */
CDC_PLAY_AUDIO|CDC_RESET|CDC_IOCTLS|CDC_DRIVE_STATUS| \
CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_GENERIC_PACKET)
static
int
sr_init
(
void
);
static
int
sr_attach
(
struct
scsi_device
*
);
static
int
sr_detect
(
struct
scsi_device
*
);
static
void
sr_detach
(
struct
scsi_device
*
);
static
int
sr_init_command
(
struct
scsi_cmnd
*
);
static
struct
Scsi_Device_Template
sr_template
=
{
...
...
@@ -77,24 +75,54 @@ static struct Scsi_Device_Template sr_template = {
.
name
=
"cdrom"
,
.
tag
=
"sr"
,
.
scsi_type
=
TYPE_ROM
,
.
blk
=
1
,
.
detect
=
sr_detect
,
.
init
=
sr_init
,
.
attach
=
sr_attach
,
.
detach
=
sr_detach
,
.
init_command
=
sr_init_command
};
static
struct
scsi_cd
*
scsi_CDs
;
static
int
sr_nr_dev
;
/* XXX(hch) bad hack, we want a bitmap instead */
static
LIST_HEAD
(
sr_devlist
);
static
spinlock_t
sr_devlist_lock
=
SPIN_LOCK_UNLOCKED
;
static
int
sr_open
(
struct
cdrom_device_info
*
,
int
);
static
void
get_sectorsize
(
struct
scsi_cd
*
);
static
void
get_capabilities
(
struct
scsi_cd
*
);
static
int
sr_init_one
(
struct
scsi_cd
*
,
int
);
static
int
sr_media_change
(
struct
cdrom_device_info
*
,
int
);
static
int
sr_packet
(
struct
cdrom_device_info
*
,
struct
cdrom_generic_command
*
);
static
Scsi_CD
*
sr_find_by_sdev
(
Scsi_Device
*
sd
)
{
struct
list_head
*
p
;
Scsi_CD
*
cd
;
spin_lock
(
&
sr_devlist_lock
);
list_for_each
(
p
,
&
sr_devlist
)
{
cd
=
list_entry
(
p
,
Scsi_CD
,
list
);
if
(
cd
->
device
==
sd
)
{
spin_unlock
(
&
sr_devlist_lock
);
return
cd
;
}
}
spin_unlock
(
&
sr_devlist_lock
);
return
NULL
;
}
static
inline
void
sr_devlist_insert
(
Scsi_CD
*
cd
)
{
spin_lock
(
&
sr_devlist_lock
);
list_add
(
&
cd
->
list
,
&
sr_devlist
);
spin_unlock
(
&
sr_devlist_lock
);
}
static
inline
void
sr_devlist_remove
(
Scsi_CD
*
cd
)
{
spin_lock
(
&
sr_devlist_lock
);
list_del
(
&
cd
->
list
);
spin_unlock
(
&
sr_devlist_lock
);
}
static
void
sr_release
(
struct
cdrom_device_info
*
cdi
)
{
struct
scsi_cd
*
cd
=
cdi
->
handle
;
...
...
@@ -466,44 +494,90 @@ static int sr_detect(struct scsi_device * SDp)
if
(
SDp
->
type
!=
TYPE_ROM
&&
SDp
->
type
!=
TYPE_WORM
)
return
0
;
sr_template
.
dev_noticed
++
;
return
1
;
}
static
int
sr_attach
(
struct
scsi_device
*
SDp
)
static
int
sr_attach
(
struct
scsi_device
*
sdev
)
{
struct
scsi_cd
*
cpnt
;
int
i
;
struct
gendisk
*
disk
;
struct
scsi_cd
*
cd
;
int
minor
;
if
(
SDp
->
type
!=
TYPE_ROM
&&
SDp
->
type
!=
TYPE_WORM
)
if
(
sdev
->
type
!=
TYPE_ROM
&&
sdev
->
type
!=
TYPE_WORM
)
return
1
;
if
(
sr_template
.
nr_dev
>=
sr_template
.
dev_max
)
if
(
scsi_slave_attach
(
sdev
))
return
1
;
cd
=
kmalloc
(
sizeof
(
*
cd
),
GFP_KERNEL
);
if
(
!
cd
)
goto
fail
;
memset
(
cd
,
0
,
sizeof
(
*
cd
));
for
(
cpnt
=
scsi_CDs
,
i
=
0
;
i
<
sr_template
.
dev_max
;
i
++
,
cpnt
++
)
if
(
!
cpnt
->
device
)
break
;
disk
=
alloc_disk
(
1
);
if
(
!
disk
)
goto
fail_free
;
if
(
i
>=
sr_template
.
dev_max
)
panic
(
"scsi_devices corrupt (sr)"
);
/*
* XXX This doesn't make us better than the previous code in the
* XXX end (not worse either, though..).
* XXX To properly support hotplugging we should have a bitmap and
* XXX use find_first_zero_bit on it. This will happen at the
* XXX same time template->nr_* goes away. --hch
*/
minor
=
sr_nr_dev
++
;
scsi_CDs
[
i
].
device
=
SDp
;
disk
->
major
=
MAJOR_NR
;
disk
->
first_minor
=
minor
;
sprintf
(
disk
->
disk_name
,
"sr%d"
,
minor
);
disk
->
fops
=
&
sr_bdops
;
disk
->
flags
=
GENHD_FL_CD
;
if
(
sr_init_one
(
cpnt
,
i
))
goto
fail
;
cd
->
device
=
sdev
;
cd
->
disk
=
disk
;
cd
->
driver
=
&
sr_template
;
cd
->
disk
=
disk
;
cd
->
capacity
=
0x1fffff
;
cd
->
needs_sector_size
=
1
;
cd
->
device
->
changed
=
1
;
/* force recheck CD type */
cd
->
use
=
1
;
cd
->
readcd_known
=
0
;
cd
->
readcd_cdda
=
0
;
cd
->
cdi
.
ops
=
&
sr_dops
;
cd
->
cdi
.
handle
=
cd
;
cd
->
cdi
.
mask
=
0
;
cd
->
cdi
.
capacity
=
1
;
sprintf
(
cd
->
cdi
.
name
,
"sr%d"
,
minor
);
sdev
->
sector_size
=
2048
;
/* A guess, just in case */
sdev
->
ten
=
1
;
sdev
->
remap
=
1
;
/* FIXME: need to handle a get_capabilities failure properly ?? */
get_capabilities
(
cd
);
sr_vendor_init
(
cd
);
sr_template
.
nr_dev
++
;
if
(
sr_template
.
nr_dev
>
sr_template
.
dev_max
)
panic
(
"scsi_devices corrupt (sr)"
);
disk
->
de
=
sdev
->
de
;
disk
->
driverfs_dev
=
&
sdev
->
sdev_driverfs_dev
;
register_cdrom
(
&
cd
->
cdi
);
set_capacity
(
disk
,
cd
->
capacity
);
disk
->
private_data
=
&
cd
->
driver
;
disk
->
queue
=
&
sdev
->
request_queue
;
printk
(
"Attached scsi CD-ROM %s at scsi%d, channel %d, id %d, lun %d
\n
"
,
scsi_CDs
[
i
].
cdi
.
name
,
SDp
->
host
->
host_no
,
SDp
->
channel
,
SDp
->
id
,
SDp
->
lun
);
add_disk
(
disk
);
sr_devlist_insert
(
cd
);
printk
(
KERN_DEBUG
"Attached scsi CD-ROM %s at scsi%d, channel %d, id %d, lun %d
\n
"
,
cd
->
cdi
.
name
,
sdev
->
host
->
host_no
,
sdev
->
channel
,
sdev
->
id
,
sdev
->
lun
);
return
0
;
fail_free:
kfree
(
cd
);
fail:
SDp
->
attached
--
;
scsi_slave_detach
(
sdev
)
;
return
1
;
}
...
...
@@ -723,126 +797,32 @@ static int sr_packet(struct cdrom_device_info *cdi,
return
cgc
->
stat
;
}
static
int
sr_registered
;
static
int
sr_init
()
{
int
i
;
if
(
sr_template
.
dev_noticed
==
0
)
return
0
;
if
(
!
sr_registered
)
{
if
(
register_blkdev
(
MAJOR_NR
,
"sr"
,
&
sr_bdops
))
{
printk
(
"Unable to get major %d for SCSI-CD
\n
"
,
MAJOR_NR
);
return
1
;
}
sr_registered
++
;
}
if
(
scsi_CDs
)
return
0
;
sr_template
.
dev_max
=
sr_template
.
dev_noticed
+
SR_EXTRA_DEVS
;
scsi_CDs
=
kmalloc
(
sr_template
.
dev_max
*
sizeof
(
struct
scsi_cd
),
GFP_ATOMIC
);
if
(
!
scsi_CDs
)
goto
cleanup_dev
;
memset
(
scsi_CDs
,
0
,
sr_template
.
dev_max
*
sizeof
(
struct
scsi_cd
));
for
(
i
=
0
;
i
<
sr_template
.
dev_max
;
i
++
)
sprintf
(
scsi_CDs
[
i
].
cdi
.
name
,
"sr%d"
,
i
);
return
0
;
cleanup_dev:
unregister_blkdev
(
MAJOR_NR
,
"sr"
);
sr_registered
--
;
return
1
;
}
static
int
sr_init_one
(
struct
scsi_cd
*
cd
,
int
first_minor
)
static
void
sr_detach
(
struct
scsi_device
*
SDp
)
{
struct
gendisk
*
disk
;
disk
=
alloc_disk
(
1
);
if
(
!
disk
)
return
-
ENOMEM
;
disk
->
major
=
MAJOR_NR
;
disk
->
first_minor
=
first_minor
;
strcpy
(
disk
->
disk_name
,
cd
->
cdi
.
name
);
disk
->
fops
=
&
sr_bdops
;
disk
->
flags
=
GENHD_FL_CD
;
cd
->
driver
=
&
sr_template
;
cd
->
disk
=
disk
;
cd
->
capacity
=
0x1fffff
;
cd
->
device
->
sector_size
=
2048
;
/* A guess, just in case */
cd
->
needs_sector_size
=
1
;
cd
->
device
->
changed
=
1
;
/* force recheck CD type */
#if 0
/* seems better to leave this for later */
get_sectorsize(cd);
printk("Scd sectorsize = %d bytes.\n", cd->sector_size);
#endif
cd
->
use
=
1
;
cd
->
device
->
ten
=
1
;
cd
->
device
->
remap
=
1
;
cd
->
readcd_known
=
0
;
cd
->
readcd_cdda
=
0
;
struct
scsi_cd
*
cd
;
cd
->
cdi
.
ops
=
&
sr_dops
;
cd
->
cdi
.
handle
=
cd
;
cd
->
cdi
.
mask
=
0
;
cd
->
cdi
.
capacity
=
1
;
/*
* FIXME: someone needs to handle a get_capabilities
* failure properly ??
*/
get_capabilities
(
cd
);
sr_vendor_init
(
cd
);
disk
->
de
=
cd
->
device
->
de
;
disk
->
driverfs_dev
=
&
cd
->
device
->
sdev_driverfs_dev
;
register_cdrom
(
&
cd
->
cdi
);
set_capacity
(
disk
,
cd
->
capacity
);
disk
->
private_data
=
&
cd
->
driver
;
disk
->
queue
=
&
cd
->
device
->
request_queue
;
add_disk
(
disk
);
return
0
;
}
cd
=
sr_find_by_sdev
(
SDp
);
if
(
!
cd
)
return
;
static
void
sr_detach
(
struct
scsi_device
*
SDp
)
{
struct
scsi_cd
*
cpnt
;
int
i
;
sr_devlist_remove
(
cd
);
del_gendisk
(
cd
->
disk
);
put_disk
(
cd
->
disk
)
;
unregister_cdrom
(
&
cd
->
cdi
)
;
for
(
cpnt
=
scsi_CDs
,
i
=
0
;
i
<
sr_template
.
dev_max
;
i
++
,
cpnt
++
)
{
if
(
cpnt
->
device
==
SDp
)
{
/*
* Since the cdrom is read-only, no need to sync
* the device.
* We should be kind to our buffer cache, however.
*/
del_gendisk
(
cpnt
->
disk
);
put_disk
(
cpnt
->
disk
);
cpnt
->
disk
=
NULL
;
scsi_slave_detach
(
SDp
);
sr_nr_dev
--
;
/*
* Reset things back to a sane state so that one can
* re-load a new driver (perhaps the same one).
*/
unregister_cdrom
(
&
(
cpnt
->
cdi
));
cpnt
->
device
=
NULL
;
cpnt
->
capacity
=
0
;
SDp
->
attached
--
;
sr_template
.
nr_dev
--
;
sr_template
.
dev_noticed
--
;
return
;
}
}
kfree
(
cd
);
}
static
int
__init
init_sr
(
void
)
{
int
rc
;
rc
=
register_blkdev
(
MAJOR_NR
,
"sr"
,
&
sr_bdops
);
if
(
rc
)
return
rc
;
return
scsi_register_device
(
&
sr_template
);
}
...
...
@@ -850,11 +830,6 @@ static void __exit exit_sr(void)
{
scsi_unregister_device
(
&
sr_template
);
unregister_blkdev
(
MAJOR_NR
,
"sr"
);
sr_registered
--
;
if
(
scsi_CDs
!=
NULL
)
kfree
(
scsi_CDs
);
sr_template
.
dev_max
=
0
;
}
module_init
(
init_sr
);
...
...
drivers/scsi/sr.h
View file @
49ce412f
...
...
@@ -26,6 +26,7 @@
typedef
struct
scsi_cd
{
struct
Scsi_Device_Template
*
driver
;
struct
list_head
list
;
unsigned
capacity
;
/* size in blocks */
Scsi_Device
*
device
;
unsigned
int
vendor
;
/* vendor code, see sr_vendor.c */
...
...
drivers/scsi/st.c
View file @
49ce412f
...
...
@@ -74,6 +74,9 @@ static int try_direct_io = TRY_DIRECT_IO;
static
int
try_rdio
=
TRUE
;
static
int
try_wdio
=
TRUE
;
static
int
st_dev_max
;
static
int
st_nr_dev
;
MODULE_AUTHOR
(
"Kai Makisara"
);
MODULE_DESCRIPTION
(
"SCSI Tape Driver"
);
MODULE_LICENSE
(
"GPL"
);
...
...
@@ -976,7 +979,7 @@ static int st_open(struct inode *inode, struct file *filp)
char
*
name
;
write_lock
(
&
st_dev_arr_lock
);
if
(
dev
>=
st_
template
.
dev_max
||
scsi_tapes
==
NULL
||
if
(
dev
>=
st_dev_max
||
scsi_tapes
==
NULL
||
((
STp
=
scsi_tapes
[
dev
])
==
NULL
))
{
write_unlock
(
&
st_dev_arr_lock
);
return
(
-
ENXIO
);
...
...
@@ -3664,6 +3667,9 @@ static int st_attach(Scsi_Device * SDp)
return
1
;
}
if
(
scsi_slave_attach
(
SDp
))
return
1
;
i
=
SDp
->
host
->
sg_tablesize
;
if
(
st_max_sg_segs
<
i
)
i
=
st_max_sg_segs
;
...
...
@@ -3680,20 +3686,20 @@ static int st_attach(Scsi_Device * SDp)
}
write_lock
(
&
st_dev_arr_lock
);
if
(
st_
template
.
nr_dev
>=
st_template
.
dev_max
)
{
if
(
st_
nr_dev
>=
st_
dev_max
)
{
Scsi_Tape
**
tmp_da
;
ST_buffer
**
tmp_ba
;
int
tmp_dev_max
;
tmp_dev_max
=
st_
template
.
nr_dev
+
ST_DEV_ARR_LUMP
;
tmp_dev_max
=
st_nr_dev
+
ST_DEV_ARR_LUMP
;
if
(
tmp_dev_max
>
ST_MAX_TAPES
)
tmp_dev_max
=
ST_MAX_TAPES
;
if
(
tmp_dev_max
<=
st_template
.
nr_dev
)
{
SDp
->
attached
--
;
if
(
tmp_dev_max
<=
st_nr_dev
)
{
write_unlock
(
&
st_dev_arr_lock
);
printk
(
KERN_ERR
"st: Too many tape devices (max. %d).
\n
"
,
ST_MAX_TAPES
);
put_disk
(
disk
);
scsi_slave_detach
(
SDp
);
return
1
;
}
...
...
@@ -3704,36 +3710,36 @@ static int st_attach(Scsi_Device * SDp)
kfree
(
tmp_da
);
if
(
tmp_ba
!=
NULL
)
kfree
(
tmp_ba
);
SDp
->
attached
--
;
write_unlock
(
&
st_dev_arr_lock
);
printk
(
KERN_ERR
"st: Can't extend device array.
\n
"
);
put_disk
(
disk
);
scsi_slave_detach
(
SDp
);
return
1
;
}
memset
(
tmp_da
,
0
,
tmp_dev_max
*
sizeof
(
Scsi_Tape
*
));
if
(
scsi_tapes
!=
NULL
)
{
memcpy
(
tmp_da
,
scsi_tapes
,
st_
template
.
dev_max
*
sizeof
(
Scsi_Tape
*
));
st_dev_max
*
sizeof
(
Scsi_Tape
*
));
kfree
(
scsi_tapes
);
}
scsi_tapes
=
tmp_da
;
st_
template
.
dev_max
=
tmp_dev_max
;
st_dev_max
=
tmp_dev_max
;
}
for
(
i
=
0
;
i
<
st_
template
.
dev_max
;
i
++
)
for
(
i
=
0
;
i
<
st_dev_max
;
i
++
)
if
(
scsi_tapes
[
i
]
==
NULL
)
break
;
if
(
i
>=
st_
template
.
dev_max
)
if
(
i
>=
st_dev_max
)
panic
(
"scsi_devices corrupt (st)"
);
tpnt
=
kmalloc
(
sizeof
(
Scsi_Tape
),
GFP_ATOMIC
);
if
(
tpnt
==
NULL
)
{
SDp
->
attached
--
;
write_unlock
(
&
st_dev_arr_lock
);
printk
(
KERN_ERR
"st: Can't allocate device descriptor.
\n
"
);
put_disk
(
disk
);
scsi_slave_detach
(
SDp
);
return
1
;
}
memset
(
tpnt
,
0
,
sizeof
(
Scsi_Tape
));
...
...
@@ -3821,7 +3827,7 @@ static int st_attach(Scsi_Device * SDp)
tpnt
->
blksize_changed
=
FALSE
;
init_MUTEX
(
&
tpnt
->
lock
);
st_
template
.
nr_dev
++
;
st_nr_dev
++
;
write_unlock
(
&
st_dev_arr_lock
);
for
(
mode
=
0
;
mode
<
ST_NBR_MODES
;
++
mode
)
{
...
...
@@ -3883,7 +3889,6 @@ static int st_detect(Scsi_Device * SDp)
{
if
(
SDp
->
type
!=
TYPE_TAPE
||
st_incompatible
(
SDp
))
return
0
;
st_template
.
dev_noticed
++
;
return
1
;
}
...
...
@@ -3893,7 +3898,7 @@ static void st_detach(Scsi_Device * SDp)
int
i
,
mode
;
write_lock
(
&
st_dev_arr_lock
);
for
(
i
=
0
;
i
<
st_
template
.
dev_max
;
i
++
)
{
for
(
i
=
0
;
i
<
st_dev_max
;
i
++
)
{
tpnt
=
scsi_tapes
[
i
];
if
(
tpnt
!=
NULL
&&
tpnt
->
device
==
SDp
)
{
tpnt
->
device
=
NULL
;
...
...
@@ -3904,9 +3909,8 @@ static void st_detach(Scsi_Device * SDp)
tpnt
->
de_n
[
mode
]
=
NULL
;
}
scsi_tapes
[
i
]
=
0
;
SDp
->
attached
--
;
st_template
.
nr_dev
--
;
st_template
.
dev_noticed
--
;
scsi_slave_detach
(
SDp
);
st_nr_dev
--
;
write_unlock
(
&
st_dev_arr_lock
);
for
(
mode
=
0
;
mode
<
ST_NBR_MODES
;
++
mode
)
{
...
...
@@ -3962,14 +3966,13 @@ static void __exit exit_st(void)
scsi_unregister_device
(
&
st_template
);
unregister_chrdev
(
SCSI_TAPE_MAJOR
,
"st"
);
if
(
scsi_tapes
!=
NULL
)
{
for
(
i
=
0
;
i
<
st_
template
.
dev_max
;
++
i
)
for
(
i
=
0
;
i
<
st_dev_max
;
++
i
)
if
(
scsi_tapes
[
i
])
{
put_disk
(
scsi_tapes
[
i
]
->
disk
);
kfree
(
scsi_tapes
[
i
]);
}
kfree
(
scsi_tapes
);
}
st_template
.
dev_max
=
0
;
printk
(
KERN_INFO
"st: Unloaded.
\n
"
);
}
...
...
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