⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scsi_target.c

📁 iscsi源代码 UNH的progect 有initiator端和target端的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		{			err = cmd[4] * BLOCKSIZE;			if (err == 0)				err = 256 * BLOCKSIZE;# ifdef DEBUG_ALLOCN_LEN			printk("get_allocation_length: READ_6/WRITE_6 length %d\n", err);# endif			break;		}# endif	default:		{			printk("get_allocation_length: unknown command 0x%02x\n", cmd[0]);			break;		}	}	return err;}#endif			     /* if !defined(DISKIO) || !defined(TRUST_CDB) */# if defined (FILEIO) || defined (MEMORYIO)/* * get_inquiry_response: This function fills in the buffer to respond to * a received SCSI INQUIRY. This function is relevant when the emulator * is responding to commands itself and not transmitting it onto a SCSI * HBA attached to the system * INPUT: Scsi_Request ptr to the inquiry, length of expected response * OUTPUT: 0 if everything is okay, < 0 if there is trouble */static int/* Bjorn Thordarson, 9-May-2004 *//*****get_inquiry_response(Scsi_Request * req, int len)*****/get_inquiry_response(Scsi_Request * req, int len, int type){	__u8 *inq;	__u8 *ptr, local_buffer[36];/* Ming Zhang, mingz@ele.uri.edu */#ifdef K26	__u8 *buffer = (void *)sg_dma_address((struct scatterlist *) req->sr_buffer);#else	__u8 *buffer = ((struct scatterlist *) req->sr_buffer)->address;#endif	/* SPC-2 says in section 7.3.2 on page 82:	 *  "The standard INQUIRY data shall contain at least 36 bytes."	 */	if (len >= 36) {		/* caller's buffer is big enough to hold all 36 bytes */		ptr = buffer;		memset(buffer, 0x00, len);	} else {		/* fill a local 36-byte buffer */		ptr = local_buffer;		memset(local_buffer, 0x00, 36);	}	/* Bjorn Thordarson, 9-May-2004 */	/*****	ptr[0] = TYPE_DISK;	*****/	ptr[0] = type;	ptr[2] = 4;		/* Device complies to this standard - SPC-2 */	ptr[3] = 2;		/* data in format specified in this standard */	ptr[4] = 31;		/* n - 4 = 35 - 4 = 31 for full 36 byte data */	ptr[6] = 0x80;		/* BQue = 1 basic task management supported */	/* SPC-2 says in section 7.3.2 on page 86:	 * "ASCII data fields shall contain only graphic codes (i.e., code	 * values 20h through 7Eh). Left-aligned fields shall place any	 * unused bytes at the end of the field (highest offset) and the	 * unused bytes shall be filled with space characters (20h)."	 */	/* 8 byte ASCII Vendor Identification of the target - left aligned */	memcpy(&ptr[8], "UNH-IOL ", 8);	/* 16 byte ASCII Product Identification of the target - left aligned */# if defined (FILEIO)	memcpy(&ptr[16], "file-mode target", 16);# else	memcpy(&ptr[16], "in-memory target", 16);#endif	/* 4 byte ASCII Product Revision Level of the target - left aligned */	memcpy(&ptr[32], "1.2 ", 4);	if (len < 36) {		/* fill as much as possible of caller's too-small buffer */		memcpy(buffer, ptr, len);	}	req->sr_result = DID_OK << 16;	if (req->sr_allowed == 1) {/* Ming Zhang, mingz@ele.uri.edu */#ifdef K26		inq = (void *)sg_dma_address((struct scatterlist *) req->sr_buffer);#else		inq = ((struct scatterlist *) req->sr_buffer)->address;#endif		inq[0] = 0x7f;	}	return 0;}/* * get_read_capacity_response: This function fills up the buffer to * respond to a received READ_CAPACITY. This function is relevant when * the emulator is responding to the commands. * INPUT: Scsi_Request pointer to the READ_CAPACITY * OUTPUT: 0 if everything is okay, < 0 if there is trouble */static int/* Bjorn Thordarson, 9-May-2004 *//*****get_read_capacity_response(Scsi_Request * req)*****/get_read_capacity_response(Target_Scsi_Cmnd *cmnd){	__u32 blocksize = BLOCKSIZE, nblocks;	__u8 *buffer;/* RDR */	nblocks = FILESIZE;#ifdef FILEIO	if (!down_interruptible(&target_map_sem)) {		if (cmnd->target_id >= MAX_TARGETS || cmnd->lun >= MAX_LUNS			|| !target_map[cmnd->target_id][cmnd->lun].in_use) {			printk("%s target id %u lun %u not in use\n",					current->comm, cmnd->target_id, cmnd->lun);			up(&target_map_sem);			return -1;		}		nblocks = target_map[cmnd->target_id][cmnd->lun].max_blocks;		up(&target_map_sem);	}#endif/* Ming Zhang, mingz@ele.uri.edu */#ifdef K26	/*****	buffer = (void *)sg_dma_address((struct scatterlist *)req->sr_buffer);	*****/	buffer = (void *)sg_dma_address((struct scatterlist *)cmnd->req->sr_buffer);#else	/*****	buffer = ((struct scatterlist *)req->sr_buffer)->address;	*****/	buffer = ((struct scatterlist *)cmnd->req->sr_buffer)->address;#endif	/* Bjorn Thordarson, 9-May-2004 -- end -- */	memset(buffer, 0x00, READ_CAP_LEN);	/* last block on the disk is (nblocks-1) */	buffer[0] = ((nblocks - 1) >> (BYTE * 3)) & 0xFF;	buffer[1] = ((nblocks - 1) >> (BYTE * 2)) & 0xFF;	buffer[2] = ((nblocks - 1) >> (BYTE)) & 0xFF;	buffer[3] = (nblocks - 1) & 0xFF;	buffer[4] = (blocksize >> (BYTE * 3)) & 0xFF;	buffer[5] = (blocksize >> (BYTE * 2)) & 0xFF;	buffer[6] = (blocksize >> BYTE) & 0xFF;	buffer[7] = blocksize & 0xFF;	/* Bjorn Thordarson, 9-May-2004 */	/*****	req->sr_result = DID_OK << 16;	*****/	cmnd->req->sr_result = DID_OK << 16;	return 0;}/* RDR */#ifdef FILEIO/* Bjorn Thordarson, 8-May-2004 -- start -- *//* get_mode_sense_response2: This function fills up the buffer to * respond to a received MODE_SENSE. This function is relevant when * the emulator is responding to the commands. * INPUT: Scsi_Request pointer to the MODE_SENSE * OUTPUT: 0 if everything is okay, < 0 if there is trouble */struct iscsi_sense_data {        u16 length;        u8  data[0];} __packed;static intget_mode_sense_response2(Scsi_Request * req, u8 sense_key, u8 asc, u8 ascq){	struct iscsi_sense_data *sense;/* Ming Zhang, mingz@ele.uri.edu */#ifdef K26        __u8 *buffer = (void *)sg_dma_address((struct scatterlist *) req->sr_buffer);#else        __u8 *buffer = ((struct scatterlist *) req->sr_buffer)->address;#endif	sense = (struct iscsi_sense_data *) buffer;	sense->length = cpu_to_be16(14);	memset(sense->data, 0, 14);	sense->data[0] = 0xf0;	sense->data[2] = sense_key;	sense->data[7] = 6;     // Additional sense length	sense->data[12] = asc;	sense->data[13] = ascq;	req->sr_result = DID_OK << 16;	return 0;}/* Bjorn Thordarson, 9-May-2004 -- end -- */#endif/* cdeng August 24 2002 * get_mode_sense_response: This function fills up the buffer to * respond to a received MODE_SENSE. This function is relevant when * the emulator is responding to the commands. * INPUT: Scsi_Request pointer to the MODE_SENSE * OUTPUT: 0 if everything is okay, < 0 if there is trouble */static intget_mode_sense_response(Scsi_Request * req, __u32 len){/* Ming Zhang, mingz@ele.uri.edu */#ifdef K26	__u8 *buffer = (void *)sg_dma_address((struct scatterlist *) req->sr_buffer);#else	__u8 *buffer = ((struct scatterlist *) req->sr_buffer)->address;#endif	memset(buffer, 0x00, len);	buffer[0] = 0x0b;			// no. of bytes that follow == 11	buffer[3] = 0x08;			// block descriptor length	buffer[10] = 0x02;			// density code and block length	req->sr_result = DID_OK << 16;	return 0;}#endif /* defined (FILEIO) || defined (MEMORYIO) */#ifndef DISKIO/* cdeng August 24 2002 * get_report_luns_response: This function fills up the buffer to * respond to a received REPORT_LUNS. This function is relevant when * the emulator is responding to the commands. * INPUT: Scsi_Request pointer to the REPORT_LUNS * OUTPUT: 0 if everything is okay, < 0 if there is trouble */static intget_report_luns_response(Target_Scsi_Cmnd *cmnd, __u32 len){	int i;	__u8 *limit, *next_slot;/* Ming Zhang, mingz@ele.uri.edu */#ifdef K26	/* Bjorn Thordarson, 9-May-2004 */	/*****	__u8 *buffer = (void *)sg_dma_address((struct scatterlist *) req->sr_buffer);	*****/	__u8 *buffer = (void *)sg_dma_address((struct scatterlist *) cmnd->req->sr_buffer);#else	/* Bjorn Thordarson, 9-May-2004 */	/*****	__u8 *buffer = ((struct scatterlist *) req->sr_buffer)->address;	*****/	__u8 *buffer = ((struct scatterlist *) cmnd->req->sr_buffer)->address;#endif	next_slot = buffer + 8;				/* first lun goes here */	limit = next_slot + len;			/* address after end of entire list */	memset(buffer, 0x00, len + 8);	/* SAM-2, section 4.12.2 LUN 0 address	 * "To address the LUN 0 of a SCSI device the peripheral device	 * address method shall be used."	 *	 * What this means is that whenever the LUN is 0, the full 8 bytes of	 * the LUN field in the iscsi PDU will also be 0. Because we have	 * already zeroed out the entire buffer above,	 * we don't need to do anything else here for lun 0.	 */	if (cmnd->target_id < MAX_TARGETS) {		if (!down_interruptible(&target_map_sem)) {			for (i = 0; i < MAX_LUNS && next_slot < limit; i++) {				if (target_map[cmnd->target_id][i].in_use) {					pack_lun(i, 0, next_slot);					next_slot += 8;;				}			}			up(&target_map_sem);		}	}	/* lun list length */	((__u32 *)buffer)[0] = cpu_to_be32(len);# ifdef DEBUG_HANDLE_CMD	/* dump out the complete REPORT LUNS response buffer */	dump_buffer(buffer, len + 8);# endif	/* change status */	cmnd->state = ST_DONE;	cmnd->req->sr_result = DID_OK << 16;	return 0;}#endif/* * hand_to_front_end: the scsi command has been tackled by the mid-level * and is now ready to be handed off to the front-end either because it * is done or because data is needed to process this command. * This function is separated only because it makes * the main code a lot cleaner. * INPUT: Scsi_Cmnd that needs to be handed off * OUTPUT: 0 if everything is okay, < 0 if there is trouble */static inthand_to_front_end(Target_Scsi_Cmnd * the_command){	Scsi_Target_Device *curr_device;# ifdef GENERICIO	__u8 *temp;# endif	/* get the device template corresponding to the device_id */	for (curr_device = target_data.st_device_list; curr_device != NULL;		 curr_device = curr_device->next) {		if (curr_device->id == the_command->dev_id)			break;	}	if (curr_device == NULL) {	/* huh - should not get here */		/*		 * That there is not a device with this id may mean		 * one of two things - there has been a mistake or		 * that the device is no longer there. For now, the		 * former is more probable		 */		printk("%s hand_to_front_end: no device with id %llu\n",			   current->comm, the_command->dev_id);		return -1;	}	/*	 * In the time that the command was processed, it could have	 * been aborted/released. We need to check this. If so, then	 * the command state is changed to ST_DEQUEUE and returned	 */	if (the_command->abort_code != CMND_OPEN) {		the_command->state = ST_DEQUEUE;		return 0;	}	if (the_command->state == ST_DONE) {# ifdef DEBUG_SCSI_THREAD		printk("%s hand_to_front_end: calling xmit_response for %p id %d\n",			   current->comm, the_command, the_command->id);# endif		if ((curr_device->template) && (curr_device->template->xmit_response)) {			/*			 * if it is generic then we need to get the			 * blocksize information from the response to			 * the READ_CAPACITY			 */# ifdef GENERICIO			if (the_command->cmd[0] == READ_CAPACITY) {				temp =					(__u8 *) ((struct scatterlist *) the_command->									   req->sr_buffer)->address;				if (the_command->target_id < MAX_TARGETS					&& the_command->lun < MAX_LUNS					&& !down_interruptible(&target_map_sem)) {					target_map[the_command->target_id][the_command->lun]						.bytes_per_block =					(temp[4] << (BYTE * 3)) + (temp[5] << (BYTE * 2)) +					(temp[6] << (BYTE)) + temp[7];				}				up(&target_map_sem);			}# endif			the_command->state = ST_HANDED;			if (curr_device->template->xmit_response(the_command)) {				printk("%s hand_to_front_end: error in xmit_response for %p "					   "id %d\n", current->comm, the_command, the_command->id);				return -1;			}		} else {			printk("%s hand_to_front_end: no xmit_response function\n",				   current->comm);			return -1;		}	} else if (the_command->state == ST_PENDING) {# ifdef DEBUG_SCSI_THREAD		printk("%s hand_to_front_end: call to rdy_to_xfer for %p id: %d\n",			   current->comm, the_command, the_command->id);# endif		if ((curr_device->template) && (curr_device->template->rdy_to_xfer)) {			the_command->state = ST_XFERRED;			if (curr_device->template->rdy_to_xfer(the_command)) {				printk("%s hand_to_front_end: error in rdy_to_xfer for %p "					   "id %d\n", current->comm, the_command, the_command->id);				return -1;			}		} else {			printk("%s hand_to_front_end: no rdy_to_xfer function\n",				   current->comm);			return -1;		}	} else {		printk("%s hand_to_front_end: command %p id: %d bad state %d\n",			   current->comm, the_command, the_command->id, the_command->state);		return -1;	}	return 0;}/* * abort_notify: This function is used to notify to the front end driver * that a command has been successfully aborted * INPUT: Target_Scsi_Cmnd * OUTPUT: none */static intabort_notify(Target_Scsi_Message * msg){	Target_Scsi_Cmnd *cmnd;	Scsi_Target_Device *curr_device;	if (msg && msg->value)		cmnd = (Target_Scsi_Cmnd *) msg->value;	else {		printk("abort_notify: null cmnd in the msg\n");		return -1;	}	/* get the device template corresponding to the device_id */	for (curr_device = target_data.st_device_list; curr_device != NULL;		 curr_device = curr_device->next) {		if (curr_device->id == cmnd->dev_id)			break;	}	if (curr_device == NULL) {		printk("abort_notify: Could not find the device\n");		return -1;	}	if ((curr_device->template) && (curr_device->template

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -