X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fscsi%2Fscsi_debug.c;h=27c633f557945f8cfb99ce433bcf53ca774f2df8;hb=490c868408bc57a756550148313ac8582fe501ef;hp=07103c399fe0c2e7ce840fcdcb7d995bd277ca73;hpb=8dea0d02f8bb7103ec0818bd2e856f30f2d1bcf1;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 07103c3..27c633f 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -94,6 +94,7 @@ static const char * scsi_debug_version_date = "20070104"; #define DEF_VIRTUAL_GB 0 #define DEF_FAKE_RW 0 #define DEF_VPD_USE_HOSTNO 1 +#define DEF_SECTOR_SIZE 512 /* bit mask values for scsi_debug_opts */ #define SCSI_DEBUG_OPT_NOISE 1 @@ -142,6 +143,7 @@ static int scsi_debug_no_lun_0 = DEF_NO_LUN_0; static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB; static int scsi_debug_fake_rw = DEF_FAKE_RW; static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO; +static int scsi_debug_sector_size = DEF_SECTOR_SIZE; static int scsi_debug_cmnd_count = 0; @@ -157,11 +159,6 @@ static int sdebug_heads; /* heads per disk */ static int sdebug_cylinders_per; /* cylinders per surface */ static int sdebug_sectors_per; /* sectors per cylinder */ -/* default sector size is 512 bytes, 2**9 bytes */ -#define POW2_SECT_SIZE 9 -#define SECT_SIZE (1 << POW2_SECT_SIZE) -#define SECT_SIZE_PER(TGT) SECT_SIZE - #define SDEBUG_MAX_PARTS 4 #define SDEBUG_SENSE_LEN 32 @@ -646,6 +643,14 @@ static int inquiry_evpd_b0(unsigned char * arr) return sizeof(vpdb0_data); } +static int inquiry_evpd_b1(unsigned char *arr) +{ + memset(arr, 0, 0x3c); + arr[0] = 0; + arr[1] = 1; + + return 0x3c; +} #define SDEBUG_LONG_INQ_SZ 96 #define SDEBUG_MAX_INQ_ARR_SZ 584 @@ -701,6 +706,7 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target, arr[n++] = 0x88; /* SCSI ports */ arr[n++] = 0x89; /* ATA information */ arr[n++] = 0xb0; /* Block limits (SBC) */ + arr[n++] = 0xb1; /* Block characteristics (SBC) */ arr[3] = n - 4; /* number of supported VPD pages */ } else if (0x80 == cmd[2]) { /* unit serial number */ arr[1] = cmd[2]; /*sanity */ @@ -740,6 +746,9 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target, } else if (0xb0 == cmd[2]) { /* Block limits (SBC) */ arr[1] = cmd[2]; /*sanity */ arr[3] = inquiry_evpd_b0(&arr[4]); + } else if (0xb1 == cmd[2]) { /* Block characteristics (SBC) */ + arr[1] = cmd[2]; /*sanity */ + arr[3] = inquiry_evpd_b1(&arr[4]); } else { /* Illegal request, invalid field in cdb */ mk_sense_buffer(devip, ILLEGAL_REQUEST, @@ -878,8 +887,8 @@ static int resp_readcap(struct scsi_cmnd * scp, arr[2] = 0xff; arr[3] = 0xff; } - arr[6] = (SECT_SIZE_PER(target) >> 8) & 0xff; - arr[7] = SECT_SIZE_PER(target) & 0xff; + arr[6] = (scsi_debug_sector_size >> 8) & 0xff; + arr[7] = scsi_debug_sector_size & 0xff; return fill_from_dev_buffer(scp, arr, SDEBUG_READCAP_ARR_SZ); } @@ -902,10 +911,10 @@ static int resp_readcap16(struct scsi_cmnd * scp, capac = sdebug_capacity - 1; for (k = 0; k < 8; ++k, capac >>= 8) arr[7 - k] = capac & 0xff; - arr[8] = (SECT_SIZE_PER(target) >> 24) & 0xff; - arr[9] = (SECT_SIZE_PER(target) >> 16) & 0xff; - arr[10] = (SECT_SIZE_PER(target) >> 8) & 0xff; - arr[11] = SECT_SIZE_PER(target) & 0xff; + arr[8] = (scsi_debug_sector_size >> 24) & 0xff; + arr[9] = (scsi_debug_sector_size >> 16) & 0xff; + arr[10] = (scsi_debug_sector_size >> 8) & 0xff; + arr[11] = scsi_debug_sector_size & 0xff; return fill_from_dev_buffer(scp, arr, min(alloc_len, SDEBUG_READCAP16_ARR_SZ)); } @@ -1019,20 +1028,20 @@ static int resp_disconnect_pg(unsigned char * p, int pcontrol, int target) static int resp_format_pg(unsigned char * p, int pcontrol, int target) { /* Format device page for mode_sense */ - unsigned char format_pg[] = {0x3, 0x16, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x40, 0, 0, 0}; - - memcpy(p, format_pg, sizeof(format_pg)); - p[10] = (sdebug_sectors_per >> 8) & 0xff; - p[11] = sdebug_sectors_per & 0xff; - p[12] = (SECT_SIZE >> 8) & 0xff; - p[13] = SECT_SIZE & 0xff; - if (DEV_REMOVEABLE(target)) - p[20] |= 0x20; /* should agree with INQUIRY */ - if (1 == pcontrol) - memset(p + 2, 0, sizeof(format_pg) - 2); - return sizeof(format_pg); + unsigned char format_pg[] = {0x3, 0x16, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0x40, 0, 0, 0}; + + memcpy(p, format_pg, sizeof(format_pg)); + p[10] = (sdebug_sectors_per >> 8) & 0xff; + p[11] = sdebug_sectors_per & 0xff; + p[12] = (scsi_debug_sector_size >> 8) & 0xff; + p[13] = scsi_debug_sector_size & 0xff; + if (DEV_REMOVEABLE(target)) + p[20] |= 0x20; /* should agree with INQUIRY */ + if (1 == pcontrol) + memset(p + 2, 0, sizeof(format_pg) - 2); + return sizeof(format_pg); } static int resp_caching_pg(unsigned char * p, int pcontrol, int target) @@ -1206,8 +1215,8 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target, ap[2] = (sdebug_capacity >> 8) & 0xff; ap[3] = sdebug_capacity & 0xff; } - ap[6] = (SECT_SIZE_PER(target) >> 8) & 0xff; - ap[7] = SECT_SIZE_PER(target) & 0xff; + ap[6] = (scsi_debug_sector_size >> 8) & 0xff; + ap[7] = scsi_debug_sector_size & 0xff; offset += bd_len; ap = arr + offset; } else if (16 == bd_len) { @@ -1215,10 +1224,10 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target, for (k = 0; k < 8; ++k, capac >>= 8) ap[7 - k] = capac & 0xff; - ap[12] = (SECT_SIZE_PER(target) >> 24) & 0xff; - ap[13] = (SECT_SIZE_PER(target) >> 16) & 0xff; - ap[14] = (SECT_SIZE_PER(target) >> 8) & 0xff; - ap[15] = SECT_SIZE_PER(target) & 0xff; + ap[12] = (scsi_debug_sector_size >> 24) & 0xff; + ap[13] = (scsi_debug_sector_size >> 16) & 0xff; + ap[14] = (scsi_debug_sector_size >> 8) & 0xff; + ap[15] = scsi_debug_sector_size & 0xff; offset += bd_len; ap = arr + offset; } @@ -1519,10 +1528,10 @@ static int do_device_access(struct scsi_cmnd *scmd, if (block + num > sdebug_store_sectors) rest = block + num - sdebug_store_sectors; - ret = func(scmd, fake_storep + (block * SECT_SIZE), - (num - rest) * SECT_SIZE); + ret = func(scmd, fake_storep + (block * scsi_debug_sector_size), + (num - rest) * scsi_debug_sector_size); if (!ret && rest) - ret = func(scmd, fake_storep, rest * SECT_SIZE); + ret = func(scmd, fake_storep, rest * scsi_debug_sector_size); return ret; } @@ -1575,10 +1584,10 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba, write_unlock_irqrestore(&atomic_rw, iflags); if (-1 == ret) return (DID_ERROR << 16); - else if ((ret < (num * SECT_SIZE)) && + else if ((ret < (num * scsi_debug_sector_size)) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) printk(KERN_INFO "scsi_debug: write: cdb indicated=%u, " - " IO sent=%d bytes\n", num * SECT_SIZE, ret); + " IO sent=%d bytes\n", num * scsi_debug_sector_size, ret); return 0; } @@ -1744,7 +1753,7 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev) open_devip = sdebug_device_create(sdbg_host, GFP_ATOMIC); if (!open_devip) { printk(KERN_ERR "%s: out of memory at line %d\n", - __FUNCTION__, __LINE__); + __func__, __LINE__); return NULL; } } @@ -1773,7 +1782,7 @@ static int scsi_debug_slave_alloc(struct scsi_device *sdp) if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %u>\n", sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); - set_bit(QUEUE_FLAG_BIDI, &sdp->request_queue->queue_flags); + queue_flag_set_unlocked(QUEUE_FLAG_BIDI, sdp->request_queue); return 0; } @@ -2085,6 +2094,7 @@ module_param_named(scsi_level, scsi_debug_scsi_level, int, S_IRUGO); module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR); module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int, S_IRUGO | S_IWUSR); +module_param_named(sector_size, scsi_debug_sector_size, int, S_IRUGO); MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert"); MODULE_DESCRIPTION("SCSI debug adapter driver"); @@ -2106,6 +2116,7 @@ MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])"); MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=5[SPC-3])"); MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)"); MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)"); +MODULE_PARM_DESC(sector_size, "hardware sector size in bytes (def=512)"); static char sdebug_info[256]; @@ -2158,8 +2169,9 @@ static int scsi_debug_proc_info(struct Scsi_Host *host, char *buffer, char **sta scsi_debug_dev_size_mb, scsi_debug_opts, scsi_debug_every_nth, scsi_debug_cmnd_count, scsi_debug_delay, scsi_debug_max_luns, scsi_debug_scsi_level, - SECT_SIZE, sdebug_cylinders_per, sdebug_heads, sdebug_sectors_per, - num_aborts, num_dev_resets, num_bus_resets, num_host_resets); + scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads, + sdebug_sectors_per, num_aborts, num_dev_resets, num_bus_resets, + num_host_resets); if (pos < offset) { len = 0; begin = pos; @@ -2434,6 +2446,12 @@ static ssize_t sdebug_vpd_use_hostno_store(struct device_driver * ddp, DRIVER_ATTR(vpd_use_hostno, S_IRUGO | S_IWUSR, sdebug_vpd_use_hostno_show, sdebug_vpd_use_hostno_store); +static ssize_t sdebug_sector_size_show(struct device_driver * ddp, char * buf) +{ + return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_sector_size); +} +DRIVER_ATTR(sector_size, S_IRUGO, sdebug_sector_size_show, NULL); + /* Note: The following function creates attribute files in the /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these files (over those found in the /sys/module/scsi_debug/parameters @@ -2459,11 +2477,13 @@ static int do_create_driverfs_files(void) ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_scsi_level); ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_virtual_gb); ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_vpd_use_hostno); + ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_sector_size); return ret; } static void do_remove_driverfs_files(void) { + driver_remove_file(&sdebug_driverfs_driver, &driver_attr_sector_size); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_vpd_use_hostno); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_virtual_gb); driver_remove_file(&sdebug_driverfs_driver, &driver_attr_scsi_level); @@ -2499,10 +2519,22 @@ static int __init scsi_debug_init(void) int k; int ret; + switch (scsi_debug_sector_size) { + case 512: + case 1024: + case 2048: + case 4096: + break; + default: + printk(KERN_ERR "scsi_debug_init: invalid sector_size %u\n", + scsi_debug_sector_size); + return -EINVAL; + } + if (scsi_debug_dev_size_mb < 1) scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */ sz = (unsigned long)scsi_debug_dev_size_mb * 1048576; - sdebug_store_sectors = sz / SECT_SIZE; + sdebug_store_sectors = sz / scsi_debug_sector_size; sdebug_capacity = get_sdebug_capacity(); /* play around with geometry, don't waste too much on track 0 */ @@ -2624,7 +2656,7 @@ static int sdebug_add_adapter(void) sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL); if (NULL == sdbg_host) { printk(KERN_ERR "%s: out of memory at line %d\n", - __FUNCTION__, __LINE__); + __func__, __LINE__); return -ENOMEM; } @@ -2635,7 +2667,7 @@ static int sdebug_add_adapter(void) sdbg_devinfo = sdebug_device_create(sdbg_host, GFP_KERNEL); if (!sdbg_devinfo) { printk(KERN_ERR "%s: out of memory at line %d\n", - __FUNCTION__, __LINE__); + __func__, __LINE__); error = -ENOMEM; goto clean; } @@ -2955,7 +2987,7 @@ static int sdebug_driver_probe(struct device * dev) hpnt = scsi_host_alloc(&sdebug_driver_template, sizeof(sdbg_host)); if (NULL == hpnt) { - printk(KERN_ERR "%s: scsi_register failed\n", __FUNCTION__); + printk(KERN_ERR "%s: scsi_register failed\n", __func__); error = -ENODEV; return error; } @@ -2970,7 +3002,7 @@ static int sdebug_driver_probe(struct device * dev) error = scsi_add_host(hpnt, &sdbg_host->dev); if (error) { - printk(KERN_ERR "%s: scsi_add_host failed\n", __FUNCTION__); + printk(KERN_ERR "%s: scsi_add_host failed\n", __func__); error = -ENODEV; scsi_host_put(hpnt); } else @@ -2989,7 +3021,7 @@ static int sdebug_driver_remove(struct device * dev) if (!sdbg_host) { printk(KERN_ERR "%s: Unable to locate host info\n", - __FUNCTION__); + __func__); return -ENODEV; }