aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorFUJITA Tomonori <tomof@acm.org>2008-01-22 11:32:01 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-01-30 14:14:25 -0500
commitc639d14e2f70d086842d37fb8e4f5ab9bd56af2e (patch)
tree7f6bd8106b7fc983d54ecb9f3cfd0e746f7fe884 /drivers
parent072d0bb3ce3507ac6e101ca8ce0b94c5777c62ed (diff)
[SCSI] scsi_debug: add XDWRITEREAD_10 support
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Acked-by: Douglas Gilbert <dougg@torque.net> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/scsi_debug.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index d810aa7aee40..1541c174937a 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -280,6 +280,8 @@ static int resp_write(struct scsi_cmnd * SCpnt, unsigned long long lba,
280 unsigned int num, struct sdebug_dev_info * devip); 280 unsigned int num, struct sdebug_dev_info * devip);
281static int resp_report_luns(struct scsi_cmnd * SCpnt, 281static int resp_report_luns(struct scsi_cmnd * SCpnt,
282 struct sdebug_dev_info * devip); 282 struct sdebug_dev_info * devip);
283static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
284 unsigned int num, struct sdebug_dev_info *devip);
283static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, 285static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
284 int arr_len); 286 int arr_len);
285static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, 287static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
@@ -334,6 +336,7 @@ static void get_data_transfer_info(unsigned char *cmd,
334 break; 336 break;
335 case WRITE_10: 337 case WRITE_10:
336 case READ_10: 338 case READ_10:
339 case XDWRITEREAD_10:
337 *lba = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24); 340 *lba = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24);
338 *num = cmd[8] + (cmd[7] << 8); 341 *num = cmd[8] + (cmd[7] << 8);
339 break; 342 break;
@@ -542,6 +545,28 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
542 case WRITE_BUFFER: 545 case WRITE_BUFFER:
543 errsts = check_readiness(SCpnt, 1, devip); 546 errsts = check_readiness(SCpnt, 1, devip);
544 break; 547 break;
548 case XDWRITEREAD_10:
549 if (!scsi_bidi_cmnd(SCpnt)) {
550 mk_sense_buffer(devip, ILLEGAL_REQUEST,
551 INVALID_FIELD_IN_CDB, 0);
552 errsts = check_condition_result;
553 break;
554 }
555
556 errsts = check_readiness(SCpnt, 0, devip);
557 if (errsts)
558 break;
559 if (scsi_debug_fake_rw)
560 break;
561 get_data_transfer_info(cmd, &lba, &num);
562 errsts = resp_read(SCpnt, lba, num, devip);
563 if (errsts)
564 break;
565 errsts = resp_write(SCpnt, lba, num, devip);
566 if (errsts)
567 break;
568 errsts = resp_xdwriteread(SCpnt, lba, num, devip);
569 break;
545 default: 570 default:
546 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) 571 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
547 printk(KERN_INFO "scsi_debug: Opcode: 0x%x not " 572 printk(KERN_INFO "scsi_debug: Opcode: 0x%x not "
@@ -1948,6 +1973,50 @@ static int resp_report_luns(struct scsi_cmnd * scp,
1948 min((int)alloc_len, SDEBUG_RLUN_ARR_SZ)); 1973 min((int)alloc_len, SDEBUG_RLUN_ARR_SZ));
1949} 1974}
1950 1975
1976static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
1977 unsigned int num, struct sdebug_dev_info *devip)
1978{
1979 int i, j, ret = -1;
1980 unsigned char *kaddr, *buf;
1981 unsigned int offset;
1982 struct scatterlist *sg;
1983 struct scsi_data_buffer *sdb = scsi_in(scp);
1984
1985 /* better not to use temporary buffer. */
1986 buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC);
1987 if (!buf)
1988 return ret;
1989
1990 offset = 0;
1991 scsi_for_each_sg(scp, sg, scsi_sg_count(scp), i) {
1992 kaddr = (unsigned char *)kmap_atomic(sg_page(sg), KM_USER0);
1993 if (!kaddr)
1994 goto out;
1995
1996 memcpy(buf + offset, kaddr + sg->offset, sg->length);
1997 offset += sg->length;
1998 kunmap_atomic(kaddr, KM_USER0);
1999 }
2000
2001 offset = 0;
2002 for_each_sg(sdb->table.sgl, sg, sdb->table.nents, i) {
2003 kaddr = (unsigned char *)kmap_atomic(sg_page(sg), KM_USER0);
2004 if (!kaddr)
2005 goto out;
2006
2007 for (j = 0; j < sg->length; j++)
2008 *(kaddr + sg->offset + j) ^= *(buf + offset + j);
2009
2010 offset += sg->length;
2011 kunmap_atomic(kaddr, KM_USER0);
2012 }
2013 ret = 0;
2014out:
2015 kfree(buf);
2016
2017 return ret;
2018}
2019
1951/* When timer goes off this function is called. */ 2020/* When timer goes off this function is called. */
1952static void timer_intr_handler(unsigned long indx) 2021static void timer_intr_handler(unsigned long indx)
1953{ 2022{
@@ -1981,6 +2050,7 @@ static int scsi_debug_slave_alloc(struct scsi_device * sdp)
1981 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) 2050 if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
1982 printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %u>\n", 2051 printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %u>\n",
1983 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); 2052 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
2053 set_bit(QUEUE_FLAG_BIDI, &sdp->request_queue->queue_flags);
1984 return 0; 2054 return 0;
1985} 2055}
1986 2056