[Stgt-devel] [Patch 6/6] Create mode page information at runtime

Mark Harvey markh794
Wed Jun 20 13:13:56 CEST 2007


FUJITA Tomonori wrote:
> From: Mark Harvey <markh794 at gmail.com>
> Subject: [Stgt-devel] [Patch 6/6] Create mode page information at runtime
> Date: Wed, 20 Jun 2007 18:09:13 +1000
>
>   
>> >From 9f725d6f1dc62143c0d7cba54db8a612a7fb5bd4 Mon Sep 17 00:00:00 2001
>> From: Mark Harvey <markh794 at gmail.com>
>> Date: Wed, 20 Jun 2007 17:52:46 +1000
>> Subject: Dynamic mode page creation.
>>
>> Mode pages are now built at run time.
>>
>> Initial configuration via the 'tgtadm --params mode_page'
>> Page information is seperated by ':'
>> e.g.
>>  --params mode_page=10:1:11:2:0:0:0:0:0:0:0:2:0:0
>> Where '10' is mode page 10
>>       '1'  is the subpage
>>       '11' is the length of the page data (11 bytes of information follow)
>>
>> The example script 'scripts/tgt-core-test' contains an executable example.
>>
>> The 'doc/README.lu_configuration' updated for mode page informaiton.
>>
>> Signed-off-by: Mark Harvey <markh794 at gmail.com>
>> ---
>>  doc/README.lu_configuration |   20 +++++
>>  scripts/tgt-core-test       |   61 ++++++++++++----
>>  usr/Makefile                |    2 +-
>>  usr/mmc.c                   |   32 ++++++++-
>>  usr/mode_page.c             |  141 ++++++++++++++++++++++++++++++++++
>>  usr/mode_page.h             |   37 +++++++++
>>     
>
> Why can't we just put them to spc.[ch]?
>
>   

No reason why not. It was just the way I did it at the time.

I'll do another patch with this merged into the spc.

Eventually, there will also be something similar to this to add LOG 
SENSE/LOG SELECT support.

I'll also add this to the spc code.


My current plan on merging code (as I write it) is:

- MODE SENSE
- Update Test unit ready to correctly handle 'removable' media flag & 
online/offline concept.
- SMC module

At this point I should be able to demonstrate a Virtual CD library.

Then add tape drive support (SSC module).

Followed by 'nice to have' SCSI OP codes like LOG SENSE / LOG SELECT & 
MODE SELECT.


Cheers
Mark

>>  usr/osd.c                   |    3 +
>>  usr/sbc.c                   |  174 +++++++++----------------------------------
>>  usr/spc.c                   |   86 +++++++++++++++++++++-
>>  usr/spc.h                   |    1 +
>>  usr/tgtd.h                  |    4 +
>>  11 files changed, 405 insertions(+), 156 deletions(-)
>>  create mode 100644 usr/mode_page.c
>>  create mode 100644 usr/mode_page.h
>>
>> diff --git a/doc/README.lu_configuration b/doc/README.lu_configuration
>> index 1244bc0..d63668a 100644
>> --- a/doc/README.lu_configuration
>> +++ b/doc/README.lu_configuration
>> @@ -65,5 +65,25 @@ standard INQUIRY:
>>  As can be seen from above 'sg_inq' output, the RMB (removable) bit is set to 1.
>>  The Unit serial number page updated with 'FRED00'
>>  
>> +Mode Page Creation
>> +------------------
>> +Create mode page '2', subpage 0 and 14 bytes of data.
>> +tgtadm --mode logicalunit --op update --tid 1 --lun 2 \
>> +         --params mode_page=2:0:14:0x80:0x80:0:0xa:0:0:0:0:0:0:0:0:0:0
>> +
>> +Create mode page '3', subpage 0 and 22 bytes of data.
>> +tgtadm --lld iscsi --mode logicalunit --op update --tid 1 --lun 2 \
>> +         --params mode_page=3:0:22:0:0:0:0:0:0:0:0:1:0:2:0:0:0:0:0:0:0:0:13:0:0
>> +
>> +Create mode page '10', subpage 0 and 10 bytes of data.
>> +tgtadm --lld iscsi --mode logicalunit --op update --tid 1 --lun 2 \
>> +         --params mode_page=10:0:10:2:0:0:0:0:0:0:0:2:0
>> +
>> +Create mode page '0x1c', subpage 0 and 10 bytes of data.
>> +tgtadm --lld iscsi --mode logicalunit --op update --tid 1 --lun 2 \
>> +         --params mode_page=0x1c:0:10:8:0:0:0:0:0:0:0:0:0
>> +
>> +
>> +
>>  Please refer to scripts/tgt-core-test for a working example.
>>  
>> diff --git a/scripts/tgt-core-test b/scripts/tgt-core-test
>> index a90fc9d..8f4d6ea 100755
>> --- a/scripts/tgt-core-test
>> +++ b/scripts/tgt-core-test
>> @@ -3,6 +3,7 @@
>>  # Parent directory for data files..
>>  HOME=/d/01
>>  
>> +# Start tgtd if not running..
>>  P=`ps -ef|grep -v grep|grep tgtd|wc -l`
>>  if [ "X"$P == "X0" ]; then
>>  	tgtd -d 1
>> @@ -48,23 +49,55 @@ tgtadm --lld iscsi --mode logicalunit --op update --tid $TID --lun $LUN \
>>  tgtadm --lld iscsi --mode logicalunit --op update --tid $TID --lun $LUN \
>>  	--params vendor_id=QUANTUM,product_id=HD100,product_rev=0010,removable=1,sense_format=0
>>  
>> -# Create 2nd LUN - CD/ROM
>> -LUN=2
>> -tgtadm --lld iscsi --mode logicalunit --op new --tid $TID --lun $LUN -b $HOME/cd_block0 --device-type=cd
>> -tgtadm --lld iscsi --mode logicalunit --op update --tid $TID --lun $LUN \
>> -	--params vendor_id=VirtualCD,product_id=CD101,product_rev=0010,scsi_sn=XYZZY11,removable=1
>> +#### Set up mode pages ####
>> +# First try a couple of attempts with incorrect data..
>>  
>> -# Create 3rd LUN - CD/ROM
>> -LUN=3
>> -tgtadm --lld iscsi --mode logicalunit --op new --tid $TID --lun $LUN -b $HOME/cd_block1 --device-type=cd
>> +# - Length too long & Incorrect value (300) as one if the params...
>>  tgtadm --lld iscsi --mode logicalunit --op update --tid $TID --lun $LUN \
>> -	--params vendor_id=VirtualCD,product_id=CD101,product_rev=0010,scsi_sn=XYZZY12,removable=1
>> -
>> -# Create 4th LUN - CD/ROM
>> -LUN=4
>> -tgtadm --lld iscsi --mode logicalunit --op new --tid $TID --lun $LUN -b $HOME/cd_block1 --device-type=cd
>> +	--params mode_page=2:0:14:0x80:0x80:0:0xa:0:300:0:0:0:0:0:0:0:0:3
>> +# - Length too short...
>> +tgtadm --lld iscsi --mode logicalunit --op update --tid $TID --lun $LUN \
>> +	--params mode_page=2:0:14:0x80:0x80:0:0xa:0:0:0:0:0:0:0:0:0
>> +# - Just right...
>> +# Vendor Uniq - Mode page 0..
>> +tgtadm --lld iscsi --mode logicalunit --op update --tid $TID --lun $LUN \
>> +	--params mode_page=0:0:0
>> +# Disconnect page
>> +tgtadm --lld iscsi --mode logicalunit --op update --tid $TID --lun $LUN \
>> +	--params mode_page=2:0:14:0x80:0x80:0:0xa:0:0:0:0:0:0:0:0:0:0
>> +# Format mode page
>> +tgtadm --lld iscsi --mode logicalunit --op update --tid $TID --lun $LUN \
>> +	--params mode_page=3:0:22:0:0:0:0:0:0:0:0:1:0:2:0:0:0:0:0:0:0:0:13:0:0
>> +# Geo mode page
>> +tgtadm --lld iscsi --mode logicalunit --op update --tid $TID --lun $LUN \
>> +	--params mode_page=4:0:22:0:0:0:0x40:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0x3a:0x98:0:0
>> +# Caching Page
>> +tgtadm --lld iscsi --mode logicalunit --op update --tid $TID --lun $LUN \
>> +	--params mode_page=8:0:18:0x14:0:0xff:0xff:0:0:0xff:0xff:0xff:0xff:0x80:0x14:0:0:0:0:0:0
>> +# ctrl mode page
>> +tgtadm --lld iscsi --mode logicalunit --op update --tid $TID --lun $LUN \
>> +	--params mode_page=10:0:10:2:0:0:0:0:0:0:0:2:0
>> +# Informational Exceptions Control Mode Page
>>  tgtadm --lld iscsi --mode logicalunit --op update --tid $TID --lun $LUN \
>> -	--params vendor_id=VirtualCD,product_id=CD101,product_rev=0010,scsi_sn=XYZZY13,removable=1
>> +	--params mode_page=0x1c:0:10:8:0:0:0:0:0:0:0:0:0
>> +
>> +
>> +
>> +for LUN in 2 3 4; do
>> +	# Create LUN - CD/ROM
>> +	tgtadm --lld iscsi --mode logicalunit --op new --tid $TID --lun $LUN -b $HOME/cd_block0 --device-type=cd
>> +	tgtadm --lld iscsi --mode logicalunit --op update --tid $TID --lun $LUN \
>> +		--params vendor_id=VirtualCD,product_id=CD101,product_rev=0010,scsi_sn=XYZZY1$LUN,removable=1
>> +	# Vendor Uniq - Mode page 0..
>> +	tgtadm --lld iscsi --mode logicalunit --op update --tid $TID --lun $LUN \
>> +		--params mode_page=0:0:0
>> +	# ctrl mode page
>> +	tgtadm --lld iscsi --mode logicalunit --op update --tid $TID --lun $LUN \
>> +		--params mode_page=10:0:10:2:0:0:0:0:0:0:0:2:0
>> +	# Informational Exceptions Control Mode Page
>> +	tgtadm --lld iscsi --mode logicalunit --op update --tid $TID --lun $LUN \
>> +		--params mode_page=0x1c:0:10:8:0:0:0:0:0:0:0:0:0
>> +done
>>  
>>  # Allow ALL initiators to connect to this target
>>  tgtadm --lld iscsi --mode target --op bind --tid $TID -I ALL
>> diff --git a/usr/Makefile b/usr/Makefile
>> index 14be34b..43a0fe6 100644
>> --- a/usr/Makefile
>> +++ b/usr/Makefile
>> @@ -44,7 +44,7 @@ CFLAGS += -Wall -g -O2 -Wstrict-prototypes -fPIC -D_LARGEFILE64_SOURCE $(INCLUDE
>>  
>>  PROGRAMS += tgtd tgtadm
>>  TGTD_OBJS += tgtd.o mgmt.o target.o spc.o sbc.o mmc.o osd.o spt.o scc.o scsi.o log.o \
>> -	driver.o util.o work.o parser.o
>> +	driver.o util.o work.o parser.o mode_page.o
>>  
>>  all: $(PROGRAMS)
>>  
>> diff --git a/usr/mmc.c b/usr/mmc.c
>> index bfcf76e..75d419a 100644
>> --- a/usr/mmc.c
>> +++ b/usr/mmc.c
>> @@ -122,6 +122,15 @@ static int mmc_read_capacity(int host_no, struct scsi_cmd *cmd)
>>  	return SAM_STAT_GOOD;
>>  }
>>  
>> +static int mmc_mode_sense(int host_no, struct scsi_cmd *cmd)
>> +{
>> +	uint8_t *scb = cmd->scb;
>> +
>> +	/* MMC devices always return descriptor block */
>> +	scb[1] |= 8;
>> +	return spc_mode_sense(host_no, cmd);
>> +}
>> +
>>  static int mmc_lu_init(struct scsi_lu *lu)
>>  {
>>  	if (spc_lu_init(lu))
>> @@ -133,6 +142,8 @@ static int mmc_lu_init(struct scsi_lu *lu)
>>  	lu->attrs.version_desc[1] = 0x0960; /* iSCSI */
>>  	lu->attrs.version_desc[2] = 0x0300; /* SPC-3 */
>>  
>> +	INIT_LIST_HEAD(&lu->mode_pages);
>> +
>>  	return 0;
>>  }
>>  
>> @@ -218,7 +229,26 @@ static struct device_type_template mmc_template = {
>>  		{spc_illegal_op,},
>>  		{spc_illegal_op,},
>>  
>> -		[0x50 ... 0x9f] = {spc_illegal_op,},
>> +		/* 0x50 */
>> +		{spc_illegal_op,},
>> +		{spc_illegal_op,},
>> +		{spc_illegal_op,},
>> +		{spc_illegal_op,},
>> +		{spc_illegal_op,},
>> +		{spc_illegal_op,},
>> +		{spc_illegal_op,},
>> +		{spc_illegal_op,},
>> +
>> +		{spc_illegal_op,},
>> +		{spc_illegal_op,},
>> +		{mmc_mode_sense,},
>> +		{spc_illegal_op,},
>> +		{spc_illegal_op,},
>> +		{spc_illegal_op,},
>> +		{spc_illegal_op,},
>> +		{spc_illegal_op,},
>> +
>> +		[0x60 ... 0x9f] = {spc_illegal_op,},
>>  
>>  		/* 0xA0 */
>>  		{spc_report_luns,},
>> diff --git a/usr/mode_page.c b/usr/mode_page.c
>> new file mode 100644
>> index 0000000..708115b
>> --- /dev/null
>> +++ b/usr/mode_page.c
>> @@ -0,0 +1,141 @@
>> +/*
>> + * Common routines with regards to SCSI mode op codes.
>> + *
>> + * Copyright (C) 2007 Mark Harvey markh794 at gmail dot com
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; version 2 of the License.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
>> + */
>> +
>> +#include <errno.h>
>> +#include <stdio.h>
>> +#include <stdlib.h>
>> +#include <string.h>
>> +#include <stdint.h>
>> +#include <unistd.h>
>> +#include <linux/fs.h>
>> +#include <string.h>
>> +
>> +#include "list.h"
>> +#include "util.h"
>> +#include "tgtd.h"
>> +#include "tgtadm_error.h"
>> +#include "mode_page.h"
>> +
>> +/*
>> + * Init and alloc space for the supported mode page structures
>> + */
>> +int insert_mode_page(struct list_head *head, int page, int subpage, int sz)
>> +{
>> +	struct mode *m;
>> +
>> +	if ((m = zalloc(sizeof(struct mode))) == NULL)
>> +		return -ENOMEM;
>> +	if ((m->mode_data = zalloc(sz)) == NULL) {
>> +		free(m);
>> +		return -ENOMEM;
>> +	}
>> +	m->pcode = page;
>> +	m->subpcode = subpage;
>> +	m->pcode_sz = (uint16_t)sz;
>> +	list_add_tail(&m->mode_siblings, head);
>> +	return 0;
>> +}
>> +
>> +struct mode *mode_page_lookup(struct list_head *head, uint8_t page)
>> +{
>> +	struct mode *m;
>> +
>> +	list_for_each_entry(m, head, mode_siblings)
>> +		if (m->pcode == page)
>> +			return m;
>> +
>> +	return NULL;
>> +}
>> +
>> +/*
>> + * Return:
>> + * 	0 on success
>> + *	TGTADM_INVALID_REQUEST on error
>> + */
>> +int add_mode_page(struct scsi_lu *lu, char *params)
>> +{
>> +	char *p = NULL;
>> +	int i = 0;
>> +	int tmp;
>> +	uint8_t page = 0;
>> +	uint8_t subpage = 0;
>> +	uint8_t *data = NULL;
>> +	uint16_t sz = 0;
>> +	struct mode *m = NULL;
>> +
>> +	while ((p = strsep(&params, ":")) != NULL) {
>> +		switch (i) {
>> +		case 0:
>> +			page = strtol(p, NULL, 0);
>> +			break;
>> +		case 1:
>> +			subpage = strtol(p, NULL, 0);
>> +			break;
>> +		case 2:
>> +			sz = strtol(p, NULL, 0);
>> +			insert_mode_page(&lu->mode_pages, page, subpage, sz);
>> +			m = mode_page_lookup(&lu->mode_pages, page);
>> +			data = m->mode_data;
>> +			break;
>> +		default:
>> +			if (i < (sz + 3)) {
>> +				tmp = strtol(p, NULL, 0);
>> +				if (tmp > 255)
>> +					dprintf("Error : Incorrect value %d "
>> +					"Mode page %d (0x%02x), index: %d\n",
>> +						tmp, page, page, i - 3);
>> +				data[i - 3] = (uint8_t)tmp;
>> +			}
>> +			break;
>> +		}
>> +		i++;
>> +	}
>> +	if (i != (sz + 3)) {
>> +		dprintf("Mode Page %d (0x%02x): param_count %d != "
>> +					" MODE PAGE size : %d\n",
>> +				page, page, i, sz + 3);
>> +		return TGTADM_INVALID_REQUEST;
>> +	} else
>> +		return TGTADM_SUCCESS;
>> +}
>> +
>> +/*
>> + * Copy mode page data from list into SCSI data so it can be returned
>> + * to the initiator
>> + *
>> + * *data -> target address (destination)
>> + * mode -> Pointer to mode page information (source)
>> + *
>> + * Returns number of bytes copied.
>> + */
>> +int build_mode_page(uint8_t *data, struct mode *m)
>> +{
>> +	uint8_t *p;
>> +	int len;
>> +
>> +	data[0] = m->pcode;
>> +	len = m->pcode_sz;
>> +	data[1] = len;
>> +	p = &data[2];
>> +	len += 2;
>> +	dprintf("Page: 0x%02x (%d)\n", m->pcode, m->pcode);
>> +	memcpy(p, m->mode_data, m->pcode_sz);
>> +
>> +return len;
>> +}
>> diff --git a/usr/mode_page.h b/usr/mode_page.h
>> new file mode 100644
>> index 0000000..31eafd3
>> --- /dev/null
>> +++ b/usr/mode_page.h
>> @@ -0,0 +1,37 @@
>> +/*
>> + * SCSI Medium Changer Command
>> + *
>> + * Copyright (C) 2007 Mark Harvey markh794 at gmail dot com
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; version 2 of the License.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
>> + */
>> +
>> +
>> +#ifndef _SPC_MODE_PG_H_
>> +#define _SPC_MODE_PG_H_
>> +
>> +struct mode {
>> +	struct list_head mode_siblings;
>> +	uint8_t pcode;		/* Page code */
>> +	uint8_t subpcode;	/* Sub page code */
>> +	int16_t pcode_sz;	/* Size of page code data. */
>> +	uint8_t *mode_data;	/* Rest of mode page info */
>> +};
>> +
>> +int insert_mode_page(struct list_head *head, int page, int subpage, int sz);
>> +struct mode *mode_page_lookup(struct list_head *head, uint8_t page);
>> +int add_mode_page(struct scsi_lu *lu, char *params);
>> +int build_mode_page(uint8_t *data, struct mode *m);
>> +
>> +#endif /* _SPC_MODE_PG_H_ */
>> diff --git a/usr/osd.c b/usr/osd.c
>> index e571ebf..684be4d 100644
>> --- a/usr/osd.c
>> +++ b/usr/osd.c
>> @@ -61,6 +61,9 @@ static int osd_lu_init(struct scsi_lu *lu)
>>  	lu->attrs.version_desc[1] = 0x0960; /* iSCSI */
>>  	lu->attrs.version_desc[2] = 0x0300; /* SPC-3 */
>>  
>> +	/* not used - but initialise anyway... */
>> +	INIT_LIST_HEAD(&lu->mode_pages);
>> +
>>  	return 0;
>>  }
>>  
>> diff --git a/usr/sbc.c b/usr/sbc.c
>> index 9d03ea4..db11381 100644
>> --- a/usr/sbc.c
>> +++ b/usr/sbc.c
>> @@ -39,6 +39,7 @@
>>  #include "scsi.h"
>>  #include "spc.h"
>>  #include "sense_codes.h"
>> +#include "mode_page.h"
>>  
>>  #define BLK_SHIFT	9
>>  
>> @@ -169,146 +170,11 @@ sense:
>>  	return SAM_STAT_CHECK_CONDITION;
>>  }
>>  
>> -static int insert_disconnect_pg(uint8_t *ptr)
>> -{
>> -	unsigned char disconnect_pg[] = {0x02, 0x0e, 0x80, 0x80, 0x00, 0x0a, 0x00, 0x00,
>> -                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
>> -
>> -	memcpy(ptr, disconnect_pg, sizeof(disconnect_pg));
>> -	return sizeof(disconnect_pg);
>> -}
>> -
>> -static int insert_caching_pg(uint8_t *ptr)
>> -{
>> -	unsigned char caching_pg[] = {0x08, 0x12, 0x14, 0x00, 0xff, 0xff, 0x00, 0x00,
>> -				      0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0x00, 0x00,
>> -				      0x00, 0x00, 0x00, 0x00};
>> -
>> -	memcpy(ptr, caching_pg, sizeof(caching_pg));
>> -	return sizeof(caching_pg);
>> -}
>> -
>> -static int insert_ctrl_m_pg(uint8_t *ptr)
>> -{
>> -	unsigned char ctrl_m_pg[] = {0x0a, 0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
>> -				     0x00, 0x00, 0x02, 0x4b};
>> -
>> -	memcpy(ptr, ctrl_m_pg, sizeof(ctrl_m_pg));
>> -	return sizeof(ctrl_m_pg);
>> -}
>> -
>> -static int insert_iec_m_pg(uint8_t *ptr)
>> -{
>> -	unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0x00, 0x00, 0x00, 0x00,
>> -				    0x00, 0x00, 0x00, 0x00, 0x00};
>> -
>> -	memcpy(ptr, iec_m_pg, sizeof(iec_m_pg));
>> -	return sizeof(iec_m_pg);
>> -}
>> -
>> -static int insert_format_m_pg(uint8_t *ptr)
>> -{
>> -	unsigned char format_m_pg[] = {0x03, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>> -				       0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00,
>> -				       0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00};
>> -	memcpy(ptr, format_m_pg, sizeof(format_m_pg));
>> -	return sizeof(format_m_pg);
>> -}
>> -
>> -static int insert_geo_m_pg(uint8_t *ptr, uint64_t sec)
>> -{
>> -	unsigned char geo_m_pg[] = {0x04, 0x16, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
>> -				    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>> -				    0x00, 0x00, 0x00, 0x00, 0x3a, 0x98, 0x00, 0x00};
>> -	uint32_t ncyl, *p;
>> -
>> -	/* assume 0xff heads, 15krpm. */
>> -	memcpy(ptr, geo_m_pg, sizeof(geo_m_pg));
>> -	ncyl = sec >> 14; /* 256 * 64 */
>> -	p = (uint32_t *)(ptr + 1);
>> -	*p = *p | __cpu_to_be32(ncyl);
>> -	return sizeof(geo_m_pg);
>> -}
>> -
>> -static int sbc_mode_sense(int host_no, struct scsi_cmd *cmd)
>> +static int sbc_lu_init(struct scsi_lu *lu)
>>  {
>> -	int ret = SAM_STAT_GOOD, len;
>> -	uint8_t pcode = cmd->scb[2] & 0x3f;
>>  	uint64_t size;
>> -	uint8_t *data = NULL;
>> -	unsigned char key = ILLEGAL_REQUEST;
>> -	uint16_t asc = E_LUN_NOT_SUPPORTED;
>> -
>> -	if (device_reserved(cmd))
>> -		return SAM_STAT_RESERVATION_CONFLICT;
>> -
>> -	data = valloc(pagesize);
>> -	if (!data) {
>> -		key = HARDWARE_ERROR;
>> -		asc = E_INTERNAL_TGT_FAILURE;
>> -		goto sense;
>> -	}
>> -	memset(data, 0, pagesize);
>> -
>> -	len = 4;
>> -	size = cmd->dev->size >> BLK_SHIFT;
>> -
>> -	if ((cmd->scb[1] & 0x8))
>> -		data[3] = 0;
>> -	else {
>> -		data[3] = 8;
>> -		len += 8;
>> -		*(uint32_t *)(data + 4) = (size >> 32) ?
>> -			__cpu_to_be32(0xffffffff) : __cpu_to_be32(size);
>> -		*(uint32_t *)(data + 8) = __cpu_to_be32(1 << BLK_SHIFT);
>> -	}
>> -
>> -	switch (pcode) {
>> -	case 0x0:
>> -		break;
>> -	case 0x2:
>> -		len += insert_disconnect_pg(data + len);
>> -		break;
>> -	case 0x3:
>> -		len += insert_format_m_pg(data + len);
>> -		break;
>> -	case 0x4:
>> -		len += insert_geo_m_pg(data + len, size);
>> -		break;
>> -	case 0x8:
>> -		len += insert_caching_pg(data + len);
>> -		break;
>> -	case 0xa:
>> -		len += insert_ctrl_m_pg(data + len);
>> -		break;
>> -	case 0x1c:
>> -		len += insert_iec_m_pg(data + len);
>> -		break;
>> -	case 0x3f:
>> -		len += insert_disconnect_pg(data + len);
>> -		len += insert_format_m_pg(data + len);
>> -		len += insert_geo_m_pg(data + len, size);
>> -		len += insert_caching_pg(data + len);
>> -		len += insert_ctrl_m_pg(data + len);
>> -		len += insert_iec_m_pg(data + len);
>> -		break;
>> -	default:
>> -		asc = E_INVALID_FIELD_IN_CDB;
>> -		goto sense;
>> -	}
>> +	uint8_t *data;
>>  
>> -	data[0] = len - 1;
>> -	cmd->len = len;
>> -	cmd->uaddr = (unsigned long) data;
>> -	return ret;
>> -sense:
>> -	cmd->len = 0;
>> -	sense_data_build(cmd, key, asc);
>> -	return SAM_STAT_CHECK_CONDITION;
>> -}
>> -
>> -static int sbc_lu_init(struct scsi_lu *lu)
>> -{
>>  	if (spc_lu_init(lu))
>>  		return -ENOMEM;
>>  
>> @@ -317,6 +183,15 @@ static int sbc_lu_init(struct scsi_lu *lu)
>>  	lu->attrs.version_desc[1] = 0x0960; /* iSCSI */
>>  	lu->attrs.version_desc[2] = 0x0300; /* SPC-3 */
>>  
>> +	INIT_LIST_HEAD(&lu->mode_pages);
>> +
>> +	data = lu->mode_block_descriptor;
>> +	size = lu->size >> BLK_SHIFT;
>> +
>> +	*(uint32_t *)(data) = (size >> 32) ?
>> +			__cpu_to_be32(0xffffffff) : __cpu_to_be32(size);
>> +	*(uint32_t *)(data + 4) = __cpu_to_be32(1 << BLK_SHIFT);
>> +
>>  	return 0;
>>  }
>>  
>> @@ -355,7 +230,7 @@ static struct device_type_template sbc_template = {
>>  
>>  		{spc_illegal_op,},
>>  		{spc_illegal_op,},
>> -		{sbc_mode_sense,},
>> +		{spc_mode_sense,},
>>  		{spc_start_stop,},
>>  		{spc_illegal_op,},
>>  		{spc_illegal_op,},
>> @@ -400,7 +275,28 @@ static struct device_type_template sbc_template = {
>>  		{spc_illegal_op,},
>>  		{spc_illegal_op,},
>>  
>> -		[0x40 ... 0x7f] = {spc_illegal_op,},
>> +		[0x40 ... 0x4f] = {spc_illegal_op,},
>> +
>> +		/* 0x50 */
>> +		{spc_illegal_op,},
>> +		{spc_illegal_op,},
>> +		{spc_illegal_op,},
>> +		{spc_illegal_op,},
>> +		{spc_illegal_op,},
>> +		{spc_illegal_op,},
>> +		{spc_illegal_op,},
>> +		{spc_illegal_op,},
>> +
>> +		{spc_illegal_op,},
>> +		{spc_illegal_op,},
>> +		{spc_mode_sense,},
>> +		{spc_illegal_op,},
>> +		{spc_illegal_op,},
>> +		{spc_illegal_op,},
>> +		{spc_illegal_op,},
>> +		{spc_illegal_op,},
>> +
>> +		[0x60 ... 0x7f] = {spc_illegal_op,},
>>  
>>  		/* 0x80 */
>>  		{spc_illegal_op,},
>> diff --git a/usr/spc.c b/usr/spc.c
>> index 6530e73..32dac79 100644
>> --- a/usr/spc.c
>> +++ b/usr/spc.c
>> @@ -35,6 +35,7 @@
>>  #include "scsi.h"
>>  #include "spc.h"
>>  #include "sense_codes.h"
>> +#include "mode_page.h"
>>  
>>  #define PRODUCT_REV	"0"
>>  #define BLK_SHIFT	9
>> @@ -231,6 +232,82 @@ int spc_test_unit(int host_no, struct scsi_cmd *cmd)
>>  		return SAM_STAT_GOOD;
>>  }
>>  
>> +/*
>> + * Reference : SPC4r11
>> + * 6.11 - MODE SENSE(6)
>> + * 6.12 - MODE SENSE(10)
>> + */
>> +int spc_mode_sense(int host_no, struct scsi_cmd *cmd)
>> +{
>> +	int	len = 0;
>> +	uint8_t *data;
>> +	uint8_t *scb = cmd->scb;
>> +	uint8_t	mode6 = (scb[0] == 0x1a) ? 1 : 0;
>> +	uint8_t dbd = (scb[1] & 8) ? 1 : 0;	/* Disable Block Descriptors */
>> +	uint8_t page_code = scb[2] & 0x3f;
>> +	uint8_t subpage = scb[3];
>> +	uint16_t alloc_len;
>> +	struct	mode	* m;
>> +	unsigned char key = ILLEGAL_REQUEST;
>> +	uint16_t asc = E_INVALID_FIELD_IN_CDB;
>> +
>> +	if (subpage)
>> +		goto sense;	/* Currently not implemented */
>> +
>> +	data = valloc(pagesize);
>> +	if (!data) {
>> +		key = HARDWARE_ERROR;
>> +		asc = E_INTERNAL_TGT_FAILURE;
>> +		goto sense;
>> +	}
>> +	memset(data, 0, pagesize);
>> +	if (mode6) {
>> +		alloc_len = scb[4];
>> +		len = 4;
>> +	} else {
>> +		alloc_len = (scb[7] << 8) + scb[8];
>> +		len = 8;
>> +	}
>> +	if (alloc_len > pagesize)
>> +		goto sense;
>> +
>> +	if (!dbd) {
>> +		memcpy(data + len, cmd->dev->mode_block_descriptor,
>> +				BLOCK_DESCRIPTOR_LEN);
>> +		len += 8;
>> +	}
>> +
>> +	if (page_code == 0x3f) {	/* All pages */
>> +		int	i;
>> +		for (i=0; i < 0x3f; i++) {
>> +			m = mode_page_lookup(&cmd->dev->mode_pages, i);
>> +			if (m)
>> +				len += build_mode_page(data + len, m);
>> +		}
>> +	} else {
>> +		m = mode_page_lookup(&cmd->dev->mode_pages, page_code);
>> +		if (!m)
>> +			goto sense;
>> +		len += build_mode_page(data + len, m);
>> +	}
>> +	if (mode6) {
>> +		data[0] = len - 1;
>> +		data[3] = (dbd) ? 0 : BLOCK_DESCRIPTOR_LEN;
>> +	} else {
>> +		*(uint16_t *)(data) = __cpu_to_be16(len - 3);
>> +		data[7] = (dbd) ? 0 : BLOCK_DESCRIPTOR_LEN;
>> +	}
>> +
>> +	cmd->len = len;
>> +	cmd->uaddr = (unsigned long)data;
>> +	return SAM_STAT_GOOD;
>> +
>> +sense:
>> +	cmd->len = 0;
>> +	sense_data_build(cmd, key, asc);
>> +	return SAM_STAT_CHECK_CONDITION;
>> +}
>> +
>>  int spc_request_sense(int host_no, struct scsi_cmd *cmd)
>>  {
>>  	uint8_t *data;
>> @@ -269,6 +346,7 @@ void dump_cdb(struct scsi_cmd *cmd)
>>  {
>>  	uint8_t *cdb = cmd->scb;
>>  
>> +	dprintf("cmd->cdb_len: %d\n", cmd->scb_len);
>>  	switch(cmd->scb_len) {
>>  	case 6:
>>  		dprintf("SCSI CMD: %02x %02x %02x %02x %02d %02x",
>> @@ -310,6 +388,7 @@ enum {
>>  	Opt_vendor_id, Opt_product_id,
>>  	Opt_product_rev, Opt_sense_format,
>>  	Opt_removable, Opt_online,
>> +	Opt_mode_page,
>>  	Opt_err,
>>  };
>>  
>> @@ -322,13 +401,14 @@ static match_table_t tokens = {
>>  	{Opt_sense_format, "sense_format=%s"},
>>  	{Opt_removable, "removable=%s"},
>>  	{Opt_online, "online=%s"},
>> +	{Opt_mode_page, "mode_page=%s"},
>>  	{Opt_err, NULL},
>>  };
>>  
>>  int spc_lu_config(struct scsi_lu *lu, char *params) {
>>  	int err = 0;
>>  	char *p;
>> -	char buf[20];
>> +	char buf[256];
>>  
>>  	if (!strncmp("targetOps", params, 9))
>>  		params = params + 10;
>> @@ -372,6 +452,10 @@ int spc_lu_config(struct scsi_lu *lu, char *params) {
>>  			match_strncpy(buf, &args[0],  sizeof(buf));
>>  			lu->attrs.online = atoi(buf);
>>  			break;
>> +		case Opt_mode_page:
>> +			match_strncpy(buf, &args[0], sizeof(buf));
>> +			err = add_mode_page(lu, buf);
>> +			break;
>>  		default:
>>  			err = TGTADM_INVALID_REQUEST;
>>  		}
>> diff --git a/usr/spc.h b/usr/spc.h
>> index 1036b70..c7b8652 100644
>> --- a/usr/spc.h
>> +++ b/usr/spc.h
>> @@ -10,5 +10,6 @@ extern int spc_illegal_op(int host_no, struct scsi_cmd *cmd);
>>  extern int spc_lu_init(struct scsi_lu *lu);
>>  extern int spc_lu_config(struct scsi_lu *lu, char * params);
>>  extern void dump_cdb(struct scsi_cmd *cmd);
>> +extern int spc_mode_sense(int host_no, struct scsi_cmd *cmd);
>>  
>>  #endif
>> diff --git a/usr/tgtd.h b/usr/tgtd.h
>> index 8e66d60..bbacae2 100644
>> --- a/usr/tgtd.h
>> +++ b/usr/tgtd.h
>> @@ -5,6 +5,7 @@
>>  
>>  #define SCSI_ID_LEN	24
>>  #define SCSI_SN_LEN	8
>> +#define BLOCK_DESCRIPTOR_LEN 8
>>  #define VERSION_DESCRIPTOR_LEN 8
>>  
>>  #define VENDOR_ID	"IET"
>> @@ -96,6 +97,9 @@ struct scsi_lu {
>>  
>>  	struct backingstore_template *bst;
>>  
>> +	uint8_t	mode_block_descriptor[BLOCK_DESCRIPTOR_LEN];
>> +	struct list_head mode_pages;
>> +
>>  	/* TODO: needs a structure for lots of device parameters */
>>  	struct lu_phy_attr attrs;
>>  };
>> -- 
>> 1.5.2.1
>>
>>
>>
>>
>>
>> _______________________________________________
>> Stgt-devel mailing list
>> Stgt-devel at lists.berlios.de
>> https://lists.berlios.de/mailman/listinfo/stgt-devel
>>
>>     
>
>   




More information about the stgt mailing list