+ Some minor formatting cleanup in the header files.

+ Properly pad the names with spaces (with thanks to Bill Studenmund)
+ Use the official T10 vendor name, "NetBSD".
+ Minor cleanup in the INQUIRY command
+ Rather than just punting on the REPORT LUNs SCSI command, emulate it
properly.  This change makes the target work with the Solaris initiator:

	AVAILABLE DISK SELECTIONS:
	       0. c1d0 <DEFAULT cyl 29728 alt 2 hd 64 sec 63>
		  /pci@0,0/pci-ide@1f,1/ide@0/cmdk@0,0
	       1. c2t5d0 <DEFAULT cyl 97 alt 2 hd 64 sec 32>
		  /iscsi/disk@0000iqn.1994-04.org.netbsd.iscsi-target%3Atarget00001,0
	Specify disk (enter its number): 1
This commit is contained in:
agc 2006-04-24 21:59:03 +00:00
parent 20862d8c44
commit 000a68021a
3 changed files with 66 additions and 30 deletions

View File

@ -40,7 +40,7 @@
*/
#define ISCSI_VENDOR "NetBSD"
#define ISCSI_PRODUCT "NetBSD/Intel iSCSI"
#define ISCSI_PRODUCT "NetBSD iSCSI"
#define ISCSI_VERSION 0
/*
@ -52,7 +52,7 @@
#define ISCSI_USE_PHASE_COLLAPSED_READ_DFLT 0
#define ISCSI_HEADER_LEN 48
#define ISCSI_PORT 3260 /* Default port */
#define ISCSI_OPCODE(HEADER) (HEADER[0]&0x3f)
#define ISCSI_OPCODE(HEADER) (HEADER[0] & 0x3f)
#define ISCSI_FIRST_BURST (ISCSI_FIRST_BURST_DFLT)
#define ISCSI_DATA_PDU_LENGTH (ISCSI_DATA_PDU_LENGTH_DFLT)
@ -360,13 +360,13 @@ typedef struct iscsi_scsi_cmd_args_t {
uint32_t bidi_trans_len;
uint32_t CmdSN;
uint32_t ExpStatSN;
uint8_t *cdb;
uint8_t *ext_cdb;
uint8_t *ahs;
uint8_t *cdb;
uint8_t *ext_cdb;
uint8_t *ahs;
uint8_t ahs_len;
uint8_t *send_data;
uint8_t *send_data;
int32_t send_sg_len;
uint8_t *recv_data;
uint8_t *recv_data;
int32_t recv_sg_len;
uint8_t status;
uint32_t bytes_sent;

View File

@ -1,4 +1,4 @@
/* $NetBSD: scsi_cmd_codes.h,v 1.4 2006/03/23 00:01:48 agc Exp $ */
/* $NetBSD: scsi_cmd_codes.h,v 1.5 2006/04/24 21:59:03 agc Exp $ */
/*
* Copyright © 2006 Alistair Crooks. All rights reserved.
@ -67,11 +67,12 @@ enum {
INQUIRY_DEVICE_IDENTIFICATION_VPD = 0x83,
INQUIRY_SUPPORTED_VPD_PAGES = 0x0,
INQUIRY_DEVICE_PIV = 0x1,
INQUIRY_DEVICE_ASSOCIATION_TARGET_PORT = 0x1,
INQUIRY_DEVICE_ASSOCIATION_TARGET_DEVICE = 0x2,
INQUIRY_DEVICE_CODESET_UTF8 = 0x3,
INQUIRY_DEVICE_ISCSI_PROTOCOL = 0x5,
INQUIRY_DEVICE_T10_VENDOR = 0x1,
INQUIRY_DEVICE_IDENTIFIER_SCSI_NAME = 0x8,
WIDE_BUS_16 = 0x20,

77
dist/iscsi/src/disk.c vendored
View File

@ -1,4 +1,4 @@
/* $NetBSD: disk.c,v 1.14 2006/04/17 16:58:31 thorpej Exp $ */
/* $NetBSD: disk.c,v 1.15 2006/04/24 21:59:03 agc Exp $ */
/*
* Copyright © 2006 Alistair Crooks. All rights reserved.
@ -740,6 +740,7 @@ disc_get_filename(disc_de_t *de)
* Public Interface (called by utarget and ktarket)
*/
/* set various global variables */
void
device_set_var(const char *var, char *arg)
{
@ -754,6 +755,7 @@ device_set_var(const char *var, char *arg)
}
}
/* allocate some space for a disk/extent, using an lseek, read and write combination */
static int
de_allocate(disc_de_t *de, char *filename)
{
@ -776,6 +778,7 @@ de_allocate(disc_de_t *de, char *filename)
return 1;
}
/* allocate space as desired */
static int
allocate_space(disc_target_t *tp)
{
@ -799,6 +802,36 @@ allocate_space(disc_target_t *tp)
return 0;
}
/* copy src to dst, of size `n' bytes, padding any extra with `pad' */
static void
strpadcpy(uint8_t *dst, size_t dstlen, const char *src, const size_t srclen, char pad)
{
int i;
if (srclen < dstlen) {
(void) memcpy(dst, src, srclen);
for (i = srclen ; i < dstlen ; i++) {
dst[i] = pad;
}
} else {
(void) memcpy(dst, src, dstlen);
}
}
/* handle REPORT LUNs SCSI command */
static int
report_luns(uint8_t *data)
{
uint64_t i;
int32_t off;
for (i = 0, off = 8 ; i < 8 ; i++, off += sizeof(i)) {
*((uint64_t *) (void *)data + off) = ISCSI_HTONLL(i);
}
*((uint32_t *) (void *)data) = ISCSI_HTONL(off - 7);
return (off - 7) * sizeof(i);
}
/* initialise the device */
int
device_init(globals_t *gp, targv_t *tvp, disc_target_t *tp)
@ -873,7 +906,6 @@ device_command(target_session_t * sess, target_cmd_t * cmd)
uint8_t *cdb = args->cdb;
uint8_t lun = (uint8_t) (args->lun >> 32);
int mode_data_len;
int done;
#if (CONFIG_DISK_INITIAL_CHECK_CONDITION==1)
static int initialized = 0;
@ -926,8 +958,8 @@ device_command(target_session_t * sess, target_cmd_t * cmd)
case INQUIRY:
iscsi_trace(TRACE_SCSI_CMD, __FILE__, __LINE__, "INQUIRY%s\n", (cdb[1] & INQUIRY_EVPD_BIT) ? " for Vital Product Data" : "");
data = args->send_data;
args->status = 0;
(void) memset(data, 0x0, (unsigned) cdb[4]); /* Clear allocated buffer */
done = 0;
if (cdb[1] & INQUIRY_EVPD_BIT) {
switch(cdb[2]) {
case INQUIRY_DEVICE_IDENTIFICATION_VPD:
@ -936,42 +968,48 @@ device_command(target_session_t * sess, target_cmd_t * cmd)
len = data[3] = cdb[4] - 7;
cp = &data[4];
cp[0] = (INQUIRY_DEVICE_ISCSI_PROTOCOL << 4) | INQUIRY_DEVICE_CODESET_UTF8;
cp[1] = (INQUIRY_DEVICE_ASSOCIATION_TARGET_DEVICE << 4) | INQUIRY_DEVICE_IDENTIFIER_SCSI_NAME;
cp[1] = (INQUIRY_DEVICE_PIV << 7) | (INQUIRY_DEVICE_ASSOCIATION_TARGET_DEVICE << 4) | INQUIRY_DEVICE_IDENTIFIER_SCSI_NAME;
len = (uint8_t) snprintf((char *)&cp[4], (int)len, "%s", sess->globals->targetname) + 4;
cp[3] = len;
cp += len;
cp[0] = (INQUIRY_DEVICE_ISCSI_PROTOCOL << 4) | INQUIRY_DEVICE_CODESET_UTF8;
cp[1] = (INQUIRY_DEVICE_ASSOCIATION_TARGET_PORT << 4) | INQUIRY_DEVICE_IDENTIFIER_SCSI_NAME;
cp[1] = (INQUIRY_DEVICE_PIV << 7) | (INQUIRY_DEVICE_ASSOCIATION_TARGET_PORT << 4) | INQUIRY_DEVICE_IDENTIFIER_SCSI_NAME;
len = (uint8_t) snprintf((char *)&cp[4], (int)len, "%s,t,0x%x", sess->globals->targetname, lun) + 4;
cp[3] = len;
done = 1;
cp += len;
cp[0] = (INQUIRY_DEVICE_ISCSI_PROTOCOL << 4) | INQUIRY_DEVICE_CODESET_UTF8;
cp[1] = (INQUIRY_DEVICE_PIV << 7) | (INQUIRY_DEVICE_ASSOCIATION_TARGET_DEVICE << 4) | INQUIRY_DEVICE_T10_VENDOR;
strpadcpy(&cp[4], 8, ISCSI_VENDOR, strlen(ISCSI_VENDOR), ' ');
cp[3] = 8;
break;
case INQUIRY_SUPPORTED_VPD_PAGES:
data[0] = DISK_PERIPHERAL_DEVICE;
data[1] = INQUIRY_SUPPORTED_VPD_PAGES;
data[3] = 2;
data[3] = 2; /* # of supported pages */
data[4] = INQUIRY_SUPPORTED_VPD_PAGES;
data[5] = INQUIRY_DEVICE_IDENTIFICATION_VPD;
done = 1;
break;
default:
iscsi_trace_error(__FILE__, __LINE__, "Unsupported INQUIRY VPD page %x\n", cdb[2]);
args->status = 0x01;
break;
}
}
if (!done) {
} else {
char versionstr[8];
data[0] = DISK_PERIPHERAL_DEVICE;
data[2] = SCSI_VERSION_SPC;
data[4] = cdb[4] - 4; /* Additional length */
data[7] |= (WIDE_BUS_32 | WIDE_BUS_16);
(void) memset(data + 8, 0x0, 32);
(void) strlcpy((char *)&data[8], ISCSI_VENDOR, 8); /* Vendor */
(void) strlcpy((char *)&data[16], ISCSI_PRODUCT, 16); /* Product ID */
(void) snprintf((char *)&data[32], 8, "%d", ISCSI_VERSION); /* Product Revision */
strpadcpy(&data[8], 8, ISCSI_VENDOR, strlen(ISCSI_VENDOR), ' ');
strpadcpy(&data[16], 16, ISCSI_PRODUCT, strlen(ISCSI_PRODUCT), ' ');
(void) snprintf(versionstr, sizeof(versionstr), "%d", ISCSI_VERSION);
strpadcpy(&data[32], 4, versionstr, strlen(versionstr), ' ');
}
if (args->status == 0) {
args->input = 1;
args->length = cdb[4] + 1;
}
args->input = 1;
args->length = cdb[4] + 1;
args->status = 0;
break;
case STOP_START_UNIT:
@ -1100,11 +1138,8 @@ device_command(target_session_t * sess, target_cmd_t * cmd)
case REPORT_LUNS:
iscsi_trace(TRACE_SCSI_CMD, __FILE__, __LINE__, "REPORT LUNS\n");
data = args->send_data;
data[3] = CONFIG_DISK_MAX_LUNS;
/* just report CONFIG_DISK_MAX_LUNS LUNs and be done with it */
args->length = report_luns(args->send_data);
args->input = 8;
args->length = 16;
args->status = 0;
break;