aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_debug.c')
-rw-r--r--drivers/scsi/scsi_debug.c110
1 files changed, 71 insertions, 39 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index f6600bfb5bde..01d11a01ffbf 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";
94#define DEF_VIRTUAL_GB 0 94#define DEF_VIRTUAL_GB 0
95#define DEF_FAKE_RW 0 95#define DEF_FAKE_RW 0
96#define DEF_VPD_USE_HOSTNO 1 96#define DEF_VPD_USE_HOSTNO 1
97#define DEF_SECTOR_SIZE 512
97 98
98/* bit mask values for scsi_debug_opts */ 99/* bit mask values for scsi_debug_opts */
99#define SCSI_DEBUG_OPT_NOISE 1 100#define SCSI_DEBUG_OPT_NOISE 1
@@ -142,6 +143,7 @@ static int scsi_debug_no_lun_0 = DEF_NO_LUN_0;
142static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB; 143static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB;
143static int scsi_debug_fake_rw = DEF_FAKE_RW; 144static int scsi_debug_fake_rw = DEF_FAKE_RW;
144static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO; 145static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO;
146static int scsi_debug_sector_size = DEF_SECTOR_SIZE;
145 147
146static int scsi_debug_cmnd_count = 0; 148static int scsi_debug_cmnd_count = 0;
147 149
@@ -157,11 +159,6 @@ static int sdebug_heads; /* heads per disk */
157static int sdebug_cylinders_per; /* cylinders per surface */ 159static int sdebug_cylinders_per; /* cylinders per surface */
158static int sdebug_sectors_per; /* sectors per cylinder */ 160static int sdebug_sectors_per; /* sectors per cylinder */
159 161
160/* default sector size is 512 bytes, 2**9 bytes */
161#define POW2_SECT_SIZE 9
162#define SECT_SIZE (1 << POW2_SECT_SIZE)
163#define SECT_SIZE_PER(TGT) SECT_SIZE
164
165#define SDEBUG_MAX_PARTS 4 162#define SDEBUG_MAX_PARTS 4
166 163
167#define SDEBUG_SENSE_LEN 32 164#define SDEBUG_SENSE_LEN 32
@@ -646,6 +643,14 @@ static int inquiry_evpd_b0(unsigned char * arr)
646 return sizeof(vpdb0_data); 643 return sizeof(vpdb0_data);
647} 644}
648 645
646static int inquiry_evpd_b1(unsigned char *arr)
647{
648 memset(arr, 0, 0x3c);
649 arr[0] = 0;
650 arr[1] = 1;
651
652 return 0x3c;
653}
649 654
650#define SDEBUG_LONG_INQ_SZ 96 655#define SDEBUG_LONG_INQ_SZ 96
651#define SDEBUG_MAX_INQ_ARR_SZ 584 656#define SDEBUG_MAX_INQ_ARR_SZ 584
@@ -701,6 +706,7 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target,
701 arr[n++] = 0x88; /* SCSI ports */ 706 arr[n++] = 0x88; /* SCSI ports */
702 arr[n++] = 0x89; /* ATA information */ 707 arr[n++] = 0x89; /* ATA information */
703 arr[n++] = 0xb0; /* Block limits (SBC) */ 708 arr[n++] = 0xb0; /* Block limits (SBC) */
709 arr[n++] = 0xb1; /* Block characteristics (SBC) */
704 arr[3] = n - 4; /* number of supported VPD pages */ 710 arr[3] = n - 4; /* number of supported VPD pages */
705 } else if (0x80 == cmd[2]) { /* unit serial number */ 711 } else if (0x80 == cmd[2]) { /* unit serial number */
706 arr[1] = cmd[2]; /*sanity */ 712 arr[1] = cmd[2]; /*sanity */
@@ -740,6 +746,9 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target,
740 } else if (0xb0 == cmd[2]) { /* Block limits (SBC) */ 746 } else if (0xb0 == cmd[2]) { /* Block limits (SBC) */
741 arr[1] = cmd[2]; /*sanity */ 747 arr[1] = cmd[2]; /*sanity */
742 arr[3] = inquiry_evpd_b0(&arr[4]); 748 arr[3] = inquiry_evpd_b0(&arr[4]);
749 } else if (0xb1 == cmd[2]) { /* Block characteristics (SBC) */
750 arr[1] = cmd[2]; /*sanity */
751 arr[3] = inquiry_evpd_b1(&arr[4]);
743 } else { 752 } else {
744 /* Illegal request, invalid field in cdb */ 753 /* Illegal request, invalid field in cdb */
745 mk_sense_buffer(devip, ILLEGAL_REQUEST, 754 mk_sense_buffer(devip, ILLEGAL_REQUEST,
@@ -878,8 +887,8 @@ static int resp_readcap(struct scsi_cmnd * scp,
878 arr[2] = 0xff; 887 arr[2] = 0xff;
879 arr[3] = 0xff; 888 arr[3] = 0xff;
880 } 889 }
881 arr[6] = (SECT_SIZE_PER(target) >> 8) & 0xff; 890 arr[6] = (scsi_debug_sector_size >> 8) & 0xff;
882 arr[7] = SECT_SIZE_PER(target) & 0xff; 891 arr[7] = scsi_debug_sector_size & 0xff;
883 return fill_from_dev_buffer(scp, arr, SDEBUG_READCAP_ARR_SZ); 892 return fill_from_dev_buffer(scp, arr, SDEBUG_READCAP_ARR_SZ);
884} 893}
885 894
@@ -902,10 +911,10 @@ static int resp_readcap16(struct scsi_cmnd * scp,
902 capac = sdebug_capacity - 1; 911 capac = sdebug_capacity - 1;
903 for (k = 0; k < 8; ++k, capac >>= 8) 912 for (k = 0; k < 8; ++k, capac >>= 8)
904 arr[7 - k] = capac & 0xff; 913 arr[7 - k] = capac & 0xff;
905 arr[8] = (SECT_SIZE_PER(target) >> 24) & 0xff; 914 arr[8] = (scsi_debug_sector_size >> 24) & 0xff;
906 arr[9] = (SECT_SIZE_PER(target) >> 16) & 0xff; 915 arr[9] = (scsi_debug_sector_size >> 16) & 0xff;
907 arr[10] = (SECT_SIZE_PER(target) >> 8) & 0xff; 916 arr[10] = (scsi_debug_sector_size >> 8) & 0xff;
908 arr[11] = SECT_SIZE_PER(target) & 0xff; 917 arr[11] = scsi_debug_sector_size & 0xff;
909 return fill_from_dev_buffer(scp, arr, 918 return fill_from_dev_buffer(scp, arr,
910 min(alloc_len, SDEBUG_READCAP16_ARR_SZ)); 919 min(alloc_len, SDEBUG_READCAP16_ARR_SZ));
911} 920}
@@ -1019,20 +1028,20 @@ static int resp_disconnect_pg(unsigned char * p, int pcontrol, int target)
1019 1028
1020static int resp_format_pg(unsigned char * p, int pcontrol, int target) 1029static int resp_format_pg(unsigned char * p, int pcontrol, int target)
1021{ /* Format device page for mode_sense */ 1030{ /* Format device page for mode_sense */
1022 unsigned char format_pg[] = {0x3, 0x16, 0, 0, 0, 0, 0, 0, 1031 unsigned char format_pg[] = {0x3, 0x16, 0, 0, 0, 0, 0, 0,
1023 0, 0, 0, 0, 0, 0, 0, 0, 1032 0, 0, 0, 0, 0, 0, 0, 0,
1024 0, 0, 0, 0, 0x40, 0, 0, 0}; 1033 0, 0, 0, 0, 0x40, 0, 0, 0};
1025 1034
1026 memcpy(p, format_pg, sizeof(format_pg)); 1035 memcpy(p, format_pg, sizeof(format_pg));
1027 p[10] = (sdebug_sectors_per >> 8) & 0xff; 1036 p[10] = (sdebug_sectors_per >> 8) & 0xff;
1028 p[11] = sdebug_sectors_per & 0xff; 1037 p[11] = sdebug_sectors_per & 0xff;
1029 p[12] = (SECT_SIZE >> 8) & 0xff; 1038 p[12] = (scsi_debug_sector_size >> 8) & 0xff;
1030 p[13] = SECT_SIZE & 0xff; 1039 p[13] = scsi_debug_sector_size & 0xff;
1031 if (DEV_REMOVEABLE(target)) 1040 if (DEV_REMOVEABLE(target))
1032 p[20] |= 0x20; /* should agree with INQUIRY */ 1041 p[20] |= 0x20; /* should agree with INQUIRY */
1033 if (1 == pcontrol) 1042 if (1 == pcontrol)
1034 memset(p + 2, 0, sizeof(format_pg) - 2); 1043 memset(p + 2, 0, sizeof(format_pg) - 2);
1035 return sizeof(format_pg); 1044 return sizeof(format_pg);
1036} 1045}
1037 1046
1038static int resp_caching_pg(unsigned char * p, int pcontrol, int target) 1047static 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,
1206 ap[2] = (sdebug_capacity >> 8) & 0xff; 1215 ap[2] = (sdebug_capacity >> 8) & 0xff;
1207 ap[3] = sdebug_capacity & 0xff; 1216 ap[3] = sdebug_capacity & 0xff;
1208 } 1217 }
1209 ap[6] = (SECT_SIZE_PER(target) >> 8) & 0xff; 1218 ap[6] = (scsi_debug_sector_size >> 8) & 0xff;
1210 ap[7] = SECT_SIZE_PER(target) & 0xff; 1219 ap[7] = scsi_debug_sector_size & 0xff;
1211 offset += bd_len; 1220 offset += bd_len;
1212 ap = arr + offset; 1221 ap = arr + offset;
1213 } else if (16 == bd_len) { 1222 } else if (16 == bd_len) {
@@ -1215,10 +1224,10 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target,
1215 1224
1216 for (k = 0; k < 8; ++k, capac >>= 8) 1225 for (k = 0; k < 8; ++k, capac >>= 8)
1217 ap[7 - k] = capac & 0xff; 1226 ap[7 - k] = capac & 0xff;
1218 ap[12] = (SECT_SIZE_PER(target) >> 24) & 0xff; 1227 ap[12] = (scsi_debug_sector_size >> 24) & 0xff;
1219 ap[13] = (SECT_SIZE_PER(target) >> 16) & 0xff; 1228 ap[13] = (scsi_debug_sector_size >> 16) & 0xff;
1220 ap[14] = (SECT_SIZE_PER(target) >> 8) & 0xff; 1229 ap[14] = (scsi_debug_sector_size >> 8) & 0xff;
1221 ap[15] = SECT_SIZE_PER(target) & 0xff; 1230 ap[15] = scsi_debug_sector_size & 0xff;
1222 offset += bd_len; 1231 offset += bd_len;
1223 ap = arr + offset; 1232 ap = arr + offset;
1224 } 1233 }
@@ -1519,10 +1528,10 @@ static int do_device_access(struct scsi_cmnd *scmd,
1519 if (block + num > sdebug_store_sectors) 1528 if (block + num > sdebug_store_sectors)
1520 rest = block + num - sdebug_store_sectors; 1529 rest = block + num - sdebug_store_sectors;
1521 1530
1522 ret = func(scmd, fake_storep + (block * SECT_SIZE), 1531 ret = func(scmd, fake_storep + (block * scsi_debug_sector_size),
1523 (num - rest) * SECT_SIZE); 1532 (num - rest) * scsi_debug_sector_size);
1524 if (!ret && rest) 1533 if (!ret && rest)
1525 ret = func(scmd, fake_storep, rest * SECT_SIZE); 1534 ret = func(scmd, fake_storep, rest * scsi_debug_sector_size);
1526 1535
1527 return ret; 1536 return ret;
1528} 1537}
@@ -1575,10 +1584,10 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
1575 write_unlock_irqrestore(&atomic_rw, iflags); 1584 write_unlock_irqrestore(&atomic_rw, iflags);
1576 if (-1 == ret) 1585 if (-1 == ret)
1577 return (DID_ERROR << 16); 1586 return (DID_ERROR << 16);
1578 else if ((ret < (num * SECT_SIZE)) && 1587 else if ((ret < (num * scsi_debug_sector_size)) &&
1579 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) 1588 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
1580 printk(KERN_INFO "scsi_debug: write: cdb indicated=%u, " 1589 printk(KERN_INFO "scsi_debug: write: cdb indicated=%u, "
1581 " IO sent=%d bytes\n", num * SECT_SIZE, ret); 1590 " IO sent=%d bytes\n", num * scsi_debug_sector_size, ret);
1582 return 0; 1591 return 0;
1583} 1592}
1584 1593
@@ -2085,6 +2094,7 @@ module_param_named(scsi_level, scsi_debug_scsi_level, int, S_IRUGO);
2085module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR); 2094module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR);
2086module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int, 2095module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int,
2087 S_IRUGO | S_IWUSR); 2096 S_IRUGO | S_IWUSR);
2097module_param_named(sector_size, scsi_debug_sector_size, int, S_IRUGO);
2088 2098
2089MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert"); 2099MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
2090MODULE_DESCRIPTION("SCSI debug adapter driver"); 2100MODULE_DESCRIPTION("SCSI debug adapter driver");
@@ -2106,6 +2116,7 @@ MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])");
2106MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=5[SPC-3])"); 2116MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=5[SPC-3])");
2107MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)"); 2117MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)");
2108MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)"); 2118MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)");
2119MODULE_PARM_DESC(sector_size, "hardware sector size in bytes (def=512)");
2109 2120
2110 2121
2111static char sdebug_info[256]; 2122static char sdebug_info[256];
@@ -2158,8 +2169,9 @@ static int scsi_debug_proc_info(struct Scsi_Host *host, char *buffer, char **sta
2158 scsi_debug_dev_size_mb, scsi_debug_opts, scsi_debug_every_nth, 2169 scsi_debug_dev_size_mb, scsi_debug_opts, scsi_debug_every_nth,
2159 scsi_debug_cmnd_count, scsi_debug_delay, 2170 scsi_debug_cmnd_count, scsi_debug_delay,
2160 scsi_debug_max_luns, scsi_debug_scsi_level, 2171 scsi_debug_max_luns, scsi_debug_scsi_level,
2161 SECT_SIZE, sdebug_cylinders_per, sdebug_heads, sdebug_sectors_per, 2172 scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads,
2162 num_aborts, num_dev_resets, num_bus_resets, num_host_resets); 2173 sdebug_sectors_per, num_aborts, num_dev_resets, num_bus_resets,
2174 num_host_resets);
2163 if (pos < offset) { 2175 if (pos < offset) {
2164 len = 0; 2176 len = 0;
2165 begin = pos; 2177 begin = pos;
@@ -2434,6 +2446,12 @@ static ssize_t sdebug_vpd_use_hostno_store(struct device_driver * ddp,
2434DRIVER_ATTR(vpd_use_hostno, S_IRUGO | S_IWUSR, sdebug_vpd_use_hostno_show, 2446DRIVER_ATTR(vpd_use_hostno, S_IRUGO | S_IWUSR, sdebug_vpd_use_hostno_show,
2435 sdebug_vpd_use_hostno_store); 2447 sdebug_vpd_use_hostno_store);
2436 2448
2449static ssize_t sdebug_sector_size_show(struct device_driver * ddp, char * buf)
2450{
2451 return scnprintf(buf, PAGE_SIZE, "%u\n", scsi_debug_sector_size);
2452}
2453DRIVER_ATTR(sector_size, S_IRUGO, sdebug_sector_size_show, NULL);
2454
2437/* Note: The following function creates attribute files in the 2455/* Note: The following function creates attribute files in the
2438 /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these 2456 /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these
2439 files (over those found in the /sys/module/scsi_debug/parameters 2457 files (over those found in the /sys/module/scsi_debug/parameters
@@ -2459,11 +2477,13 @@ static int do_create_driverfs_files(void)
2459 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_scsi_level); 2477 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_scsi_level);
2460 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_virtual_gb); 2478 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_virtual_gb);
2461 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_vpd_use_hostno); 2479 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_vpd_use_hostno);
2480 ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_sector_size);
2462 return ret; 2481 return ret;
2463} 2482}
2464 2483
2465static void do_remove_driverfs_files(void) 2484static void do_remove_driverfs_files(void)
2466{ 2485{
2486 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_sector_size);
2467 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_vpd_use_hostno); 2487 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_vpd_use_hostno);
2468 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_virtual_gb); 2488 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_virtual_gb);
2469 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_scsi_level); 2489 driver_remove_file(&sdebug_driverfs_driver, &driver_attr_scsi_level);
@@ -2499,10 +2519,22 @@ static int __init scsi_debug_init(void)
2499 int k; 2519 int k;
2500 int ret; 2520 int ret;
2501 2521
2522 switch (scsi_debug_sector_size) {
2523 case 512:
2524 case 1024:
2525 case 2048:
2526 case 4096:
2527 break;
2528 default:
2529 printk(KERN_ERR "scsi_debug_init: invalid sector_size %u\n",
2530 scsi_debug_sector_size);
2531 return -EINVAL;
2532 }
2533
2502 if (scsi_debug_dev_size_mb < 1) 2534 if (scsi_debug_dev_size_mb < 1)
2503 scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */ 2535 scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */
2504 sz = (unsigned long)scsi_debug_dev_size_mb * 1048576; 2536 sz = (unsigned long)scsi_debug_dev_size_mb * 1048576;
2505 sdebug_store_sectors = sz / SECT_SIZE; 2537 sdebug_store_sectors = sz / scsi_debug_sector_size;
2506 sdebug_capacity = get_sdebug_capacity(); 2538 sdebug_capacity = get_sdebug_capacity();
2507 2539
2508 /* play around with geometry, don't waste too much on track 0 */ 2540 /* play around with geometry, don't waste too much on track 0 */