Commit 0dc70072 authored by James Bottomley's avatar James Bottomley

Merge mulgrave.(none):/home/jejb/BK/linux-2.5

into mulgrave.(none):/home/jejb/BK/scsi-for-linus-2.5
parents db01fdce f1c5d5cd
......@@ -3137,14 +3137,14 @@ 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,44)
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,43)
static int sbp2scsi_biosparam (struct scsi_device *sdev,
struct block_device *dev, sector_t capacy, int geom[])
struct block_device *dev, sector_t capacity, int geom[])
{
#else
static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[])
{
sector_t capacy = disk->capacity;
sector_t capacity = disk->capacity;
#endif
int heads, sectors, cylinders;
......
......@@ -552,7 +552,8 @@ void sbp2scsi_setup(char *str, int *ints);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28)
static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[]);
#else
static int sbp2scsi_biosparam (Scsi_Disk *disk, struct block_device *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);
......
......@@ -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
......
......@@ -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 */
......@@ -115,7 +111,6 @@ int scsi_host_chk_and_release(struct Scsi_Host *shost)
{
int pcount;
Scsi_Device *sdev;
struct Scsi_Device_Template *sdev_tp;
Scsi_Cmnd *scmd;
/*
......@@ -175,10 +170,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) {
......@@ -471,12 +463,9 @@ 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);
/*
* Check no detect routine.
*/
......@@ -526,8 +515,6 @@ int scsi_register_host(Scsi_Host_Template *shost_tp)
}
}
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
*/
......@@ -549,31 +536,15 @@ int scsi_register_host(Scsi_Host_Template *shost_tp)
}
}
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
*/
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)
if (sdev->host->hostt == shost_tp)
if (scsi_attach_device(sdev))
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);
}
}
}
}
......@@ -614,14 +585,6 @@ int scsi_unregister_host(Scsi_Host_Template *shost_tp)
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();
......
......@@ -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;
......@@ -520,8 +517,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 *);
......@@ -605,28 +600,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
......
......@@ -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;
/*
......
......@@ -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 *);
......
......@@ -163,7 +163,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
};
......@@ -5411,6 +5410,8 @@ 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;
......
......@@ -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.
......@@ -1718,7 +1724,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;
......@@ -1924,12 +1929,7 @@ 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) {
/*
......@@ -1969,6 +1969,56 @@ 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)
sdev->attached += (*sdt->detect)(sdev);
up_read(&scsi_devicelist_mutex);
}
int scsi_attach_device(struct scsi_device *sdev)
{
struct Scsi_Device_Template *sdt;
scsi_build_commandblocks(sdev);
if (sdev->current_queue_depth == 0)
goto fail;
down_read(&scsi_devicelist_mutex);
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);
up_read(&scsi_devicelist_mutex);
if (!sdev->attached)
scsi_release_commandblocks(sdev);
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);
}
/*
* This entry point should be called by a loadable module if it is trying
* add a high level scsi driver to the system.
......@@ -1987,8 +2037,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;
......@@ -2094,6 +2146,7 @@ int scsi_unregister_device(struct Scsi_Device_Template *tpnt)
/*
* Extract the template from the linked list.
*/
down_write(&scsi_devicelist_mutex);
spnt = scsi_devicelist;
prev_spnt = NULL;
while (spnt != tpnt) {
......@@ -2104,6 +2157,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();
......
......@@ -478,6 +478,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.
......
......@@ -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.62 (20020812)";
static const char * scsi_debug_version_str = "Version: 1.63 (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_Cmnd *);
typedef void (* done_funct_t) (struct scsi_cmnd *);
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(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_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_Cmnd *scmd);
static struct sdebug_dev_info * devInfoReg(struct scsi_cmnd *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_Cmnd * SCpnt, done_funct_t done)
int scsi_debug_queuecommand(struct scsi_cmnd * 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_Device *dev, int cmd, void *arg)
static int scsi_debug_ioctl(struct scsi_device *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_Cmnd * SCpnt, struct sdebug_dev_info * devip)
static int check_reset(struct scsi_cmnd * 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();
#ifdef DRIVERFS_SUPPORT
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
tpnt->proc_name = (char *)sdebug_proc_name;
for (num_present = 0, k = 0; k < NR_HOSTS_PRESENT; k++) {
if (NULL == scsi_register(tpnt, 0))
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
++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();
else {
hpnt->max_lun = scsi_debug_max_luns;
++num_hosts_present;
}
}
#endif
return num_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)
{
if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
printk(KERN_INFO "scsi_debug: release\n");
stop_all_queued();
scsi_unregister(hpnt);
if (++num_releases == num_present) {
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: [last] release, "
"host_no=%u\n", host_no);
num_releases = 0;
initialized = 0;
stop_all_queued();
#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;
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_Cmnd * SCpnt)
static int scsi_debug_abort(struct scsi_cmnd * 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_Cmnd * SCpnt)
static int scsi_debug_device_reset(struct scsi_cmnd * 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_Cmnd * SCpnt)
static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt)
{
Scsi_Device * sdp;
struct scsi_device * 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_Cmnd * SCpnt)
static int scsi_debug_host_reset(struct scsi_cmnd * 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\nnumber 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);
......
......@@ -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_Cmnd *);
static int scsi_debug_bus_reset(Scsi_Cmnd *);
static int scsi_debug_device_reset(Scsi_Cmnd *);
static int scsi_debug_host_reset(Scsi_Cmnd *);
static int scsi_debug_abort(struct scsi_cmnd *);
static int scsi_debug_bus_reset(struct scsi_cmnd *);
static int scsi_debug_device_reset(struct scsi_cmnd *);
static int scsi_debug_host_reset(struct scsi_cmnd *);
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,
......
......@@ -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,9 +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);
scsi_detect_device(sdev);
if (sdev->host->hostt->slave_attach != NULL) {
if (sdev->host->hostt->slave_attach(sdev) != 0) {
......@@ -2010,7 +2007,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 +2024,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);
}
/**
......
......@@ -92,7 +92,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);
/*
......
......@@ -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
};
......@@ -1344,55 +1342,6 @@ sg_detect(Scsi_Device * scsidp)
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)
......@@ -1643,9 +1592,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
......
......@@ -65,7 +65,6 @@ 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 *);
......@@ -79,22 +78,52 @@ static struct Scsi_Device_Template sr_template = {
.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 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;
......@@ -470,40 +499,84 @@ static int sr_detect(struct scsi_device * SDp)
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)
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_template.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);
sr_template.nr_dev++;
if (sr_template.nr_dev > sr_template.dev_max)
panic("scsi_devices corrupt (sr)");
sdev->sector_size = 2048; /* A guess, just in case */
sdev->ten = 1;
sdev->remap = 1;
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);
/* FIXME: need to handle a get_capabilities failure properly ?? */
get_capabilities(cd);
sr_vendor_init(cd);
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;
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--;
sdev->attached--;
return 1;
}
......@@ -723,126 +796,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;
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);
struct scsi_cd *cd;
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;
SDp->attached--;
sr_template.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 +829,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);
......
......@@ -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 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment