aachba.c

来自「linux 内核源代码」· C语言 代码 · 共 2,197 行 · 第 1/5 页

C
2,197
字号
					(cmd->cmnd[7] << 16) |					(cmd->cmnd[8] << 8) |					cmd->cmnd[9];				cmnd_count = (cmd->cmnd[10] << 24) |					(cmd->cmnd[11] << 16) |					(cmd->cmnd[12] << 8) |					cmd->cmnd[13];			} else if (cmd->cmnd[0] == WRITE_12) {				cmnd_lba = ((u64)cmd->cmnd[2] << 24) |					(cmd->cmnd[3] << 16) |					(cmd->cmnd[4] << 8) |					cmd->cmnd[5];				cmnd_count = (cmd->cmnd[6] << 24) |					(cmd->cmnd[7] << 16) |					(cmd->cmnd[8] << 8) |					cmd->cmnd[9];			} else if (cmd->cmnd[0] == WRITE_10) {				cmnd_lba = ((u64)cmd->cmnd[2] << 24) |					(cmd->cmnd[3] << 16) |					(cmd->cmnd[4] << 8) |					cmd->cmnd[5];				cmnd_count = (cmd->cmnd[7] << 8) |					cmd->cmnd[8];			} else				continue;			if (((cmnd_lba + cmnd_count) < lba) ||			  (count && ((lba + count) < cmnd_lba)))				continue;			++active;			break;		}	spin_unlock_irqrestore(&sdev->list_lock, flags);	/*	 *	Yield the processor (requeue for later)	 */	if (active)		return SCSI_MLQUEUE_DEVICE_BUSY;	aac = (struct aac_dev *)scsicmd->device->host->hostdata;	if (aac->in_reset)		return SCSI_MLQUEUE_HOST_BUSY;	/*	 *	Allocate and initialize a Fib	 */	if (!(cmd_fibcontext = aac_fib_alloc(aac)))		return SCSI_MLQUEUE_HOST_BUSY;	aac_fib_init(cmd_fibcontext);	synchronizecmd = fib_data(cmd_fibcontext);	synchronizecmd->command = cpu_to_le32(VM_ContainerConfig);	synchronizecmd->type = cpu_to_le32(CT_FLUSH_CACHE);	synchronizecmd->cid = cpu_to_le32(scmd_id(scsicmd));	synchronizecmd->count =	     cpu_to_le32(sizeof(((struct aac_synchronize_reply *)NULL)->data));	/*	 *	Now send the Fib to the adapter	 */	status = aac_fib_send(ContainerCommand,		  cmd_fibcontext,		  sizeof(struct aac_synchronize),		  FsaNormal,		  0, 1,		  (fib_callback)synchronize_callback,		  (void *)scsicmd);	/*	 *	Check that the command queued to the controller	 */	if (status == -EINPROGRESS) {		scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;		return 0;	}	printk(KERN_WARNING		"aac_synchronize: aac_fib_send failed with status: %d.\n", status);	aac_fib_complete(cmd_fibcontext);	aac_fib_free(cmd_fibcontext);	return SCSI_MLQUEUE_HOST_BUSY;}/** *	aac_scsi_cmd()		-	Process SCSI command *	@scsicmd:		SCSI command block * *	Emulate a SCSI command and queue the required request for the *	aacraid firmware. */ int aac_scsi_cmd(struct scsi_cmnd * scsicmd){	u32 cid;	struct Scsi_Host *host = scsicmd->device->host;	struct aac_dev *dev = (struct aac_dev *)host->hostdata;	struct fsa_dev_info *fsa_dev_ptr = dev->fsa_dev;		if (fsa_dev_ptr == NULL)		return -1;	/*	 *	If the bus, id or lun is out of range, return fail	 *	Test does not apply to ID 16, the pseudo id for the controller	 *	itself.	 */	cid = scmd_id(scsicmd);	if (cid != host->this_id) {		if (scmd_channel(scsicmd) == CONTAINER_CHANNEL) {			if((cid >= dev->maximum_num_containers) ||					(scsicmd->device->lun != 0)) {				scsicmd->result = DID_NO_CONNECT << 16;				scsicmd->scsi_done(scsicmd);				return 0;			}			/*			 *	If the target container doesn't exist, it may have			 *	been newly created			 */			if ((fsa_dev_ptr[cid].valid & 1) == 0) {				switch (scsicmd->cmnd[0]) {				case SERVICE_ACTION_IN:					if (!(dev->raw_io_interface) ||					    !(dev->raw_io_64) ||					    ((scsicmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16))						break;				case INQUIRY:				case READ_CAPACITY:				case TEST_UNIT_READY:					if (dev->in_reset)						return -1;					return _aac_probe_container(scsicmd,							aac_probe_container_callback2);				default:					break;				}			}		} else {  /* check for physical non-dasd devices */			if ((dev->nondasd_support == 1) || expose_physicals) {				if (dev->in_reset)					return -1;				return aac_send_srb_fib(scsicmd);			} else {				scsicmd->result = DID_NO_CONNECT << 16;				scsicmd->scsi_done(scsicmd);				return 0;			}		}	}	/*	 * else Command for the controller itself	 */	else if ((scsicmd->cmnd[0] != INQUIRY) &&	/* only INQUIRY & TUR cmnd supported for controller */		(scsicmd->cmnd[0] != TEST_UNIT_READY)) 	{		dprintk((KERN_WARNING "Only INQUIRY & TUR command supported for controller, rcvd = 0x%x.\n", scsicmd->cmnd[0]));		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;		set_sense((u8 *) &dev->fsa_dev[cid].sense_data,			    ILLEGAL_REQUEST,			    SENCODE_INVALID_COMMAND,			    ASENCODE_INVALID_COMMAND, 0, 0, 0, 0);		memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,		  (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(scsicmd->sense_buffer))		    ? sizeof(scsicmd->sense_buffer)		    : sizeof(dev->fsa_dev[cid].sense_data));		scsicmd->scsi_done(scsicmd);		return 0;	}	/* Handle commands here that don't really require going out to the adapter */	switch (scsicmd->cmnd[0]) {	case INQUIRY:	{		struct inquiry_data inq_data;		dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", cid));		memset(&inq_data, 0, sizeof (struct inquiry_data));		if (scsicmd->cmnd[1] & 0x1 ) {			char *arr = (char *)&inq_data;			/* EVPD bit set */			arr[0] = (scmd_id(scsicmd) == host->this_id) ?			  INQD_PDT_PROC : INQD_PDT_DA;			if (scsicmd->cmnd[2] == 0) {				/* supported vital product data pages */				arr[3] = 2;				arr[4] = 0x0;				arr[5] = 0x80;				arr[1] = scsicmd->cmnd[2];				aac_internal_transfer(scsicmd, &inq_data, 0,				  sizeof(inq_data));				scsicmd->result = DID_OK << 16 |				  COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;			} else if (scsicmd->cmnd[2] == 0x80) {				/* unit serial number page */				arr[3] = setinqserial(dev, &arr[4],				  scmd_id(scsicmd));				arr[1] = scsicmd->cmnd[2];				aac_internal_transfer(scsicmd, &inq_data, 0,				  sizeof(inq_data));				return aac_get_container_serial(scsicmd);			} else {				/* vpd page not implemented */				scsicmd->result = DID_OK << 16 |				  COMMAND_COMPLETE << 8 |				  SAM_STAT_CHECK_CONDITION;				set_sense((u8 *) &dev->fsa_dev[cid].sense_data,				  ILLEGAL_REQUEST,				  SENCODE_INVALID_CDB_FIELD,				  ASENCODE_NO_SENSE, 0, 7, 2, 0);				memcpy(scsicmd->sense_buffer,				  &dev->fsa_dev[cid].sense_data,				  (sizeof(dev->fsa_dev[cid].sense_data) >				    sizeof(scsicmd->sense_buffer))				       ? sizeof(scsicmd->sense_buffer)				       : sizeof(dev->fsa_dev[cid].sense_data));			}			scsicmd->scsi_done(scsicmd);			return 0;		}		inq_data.inqd_ver = 2;	/* claim compliance to SCSI-2 */		inq_data.inqd_rdf = 2;	/* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */		inq_data.inqd_len = 31;		/*Format for "pad2" is  RelAdr | WBus32 | WBus16 |  Sync  | Linked |Reserved| CmdQue | SftRe */		inq_data.inqd_pad2= 0x32 ;	 /*WBus16|Sync|CmdQue */		/*		 *	Set the Vendor, Product, and Revision Level		 *	see: <vendor>.c i.e. aac.c		 */		if (cid == host->this_id) {			setinqstr(dev, (void *) (inq_data.inqd_vid), ARRAY_SIZE(container_types));			inq_data.inqd_pdt = INQD_PDT_PROC;	/* Processor device */			aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));			scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;			scsicmd->scsi_done(scsicmd);			return 0;		}		if (dev->in_reset)			return -1;		setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type);		inq_data.inqd_pdt = INQD_PDT_DA;	/* Direct/random access device */		aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));		return aac_get_container_name(scsicmd);	}	case SERVICE_ACTION_IN:		if (!(dev->raw_io_interface) ||		    !(dev->raw_io_64) ||		    ((scsicmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16))			break;	{		u64 capacity;		char cp[13];		dprintk((KERN_DEBUG "READ CAPACITY_16 command.\n"));		capacity = fsa_dev_ptr[cid].size - 1;		cp[0] = (capacity >> 56) & 0xff;		cp[1] = (capacity >> 48) & 0xff;		cp[2] = (capacity >> 40) & 0xff;		cp[3] = (capacity >> 32) & 0xff;		cp[4] = (capacity >> 24) & 0xff;		cp[5] = (capacity >> 16) & 0xff;		cp[6] = (capacity >> 8) & 0xff;		cp[7] = (capacity >> 0) & 0xff;		cp[8] = 0;		cp[9] = 0;		cp[10] = 2;		cp[11] = 0;		cp[12] = 0;		aac_internal_transfer(scsicmd, cp, 0,		  min_t(size_t, scsicmd->cmnd[13], sizeof(cp)));		if (sizeof(cp) < scsicmd->cmnd[13]) {			unsigned int len, offset = sizeof(cp);			memset(cp, 0, offset);			do {				len = min_t(size_t, scsicmd->cmnd[13] - offset,						sizeof(cp));				aac_internal_transfer(scsicmd, cp, offset, len);			} while ((offset += len) < scsicmd->cmnd[13]);		}		/* Do not cache partition table for arrays */		scsicmd->device->removable = 1;		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;		scsicmd->scsi_done(scsicmd);		return 0;	}	case READ_CAPACITY:	{		u32 capacity;		char cp[8];		dprintk((KERN_DEBUG "READ CAPACITY command.\n"));		if (fsa_dev_ptr[cid].size <= 0x100000000ULL)			capacity = fsa_dev_ptr[cid].size - 1;		else			capacity = (u32)-1;		cp[0] = (capacity >> 24) & 0xff;		cp[1] = (capacity >> 16) & 0xff;		cp[2] = (capacity >> 8) & 0xff;		cp[3] = (capacity >> 0) & 0xff;		cp[4] = 0;		cp[5] = 0;		cp[6] = 2;		cp[7] = 0;		aac_internal_transfer(scsicmd, cp, 0, sizeof(cp));		/* Do not cache partition table for arrays */		scsicmd->device->removable = 1;		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;		scsicmd->scsi_done(scsicmd);		return 0;	}	case MODE_SENSE:	{		char mode_buf[7];		int mode_buf_length = 4;		dprintk((KERN_DEBUG "MODE SENSE command.\n"));		mode_buf[0] = 3;	/* Mode data length */		mode_buf[1] = 0;	/* Medium type - default */		mode_buf[2] = 0;	/* Device-specific param,					   bit 8: 0/1 = write enabled/protected					   bit 4: 0/1 = FUA enabled */		if (dev->raw_io_interface)			mode_buf[2] = 0x10;		mode_buf[3] = 0;	/* Block descriptor length */		if (((scsicmd->cmnd[2] & 0x3f) == 8) ||		  ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) {			mode_buf[0] = 6;			mode_buf[4] = 8;			mode_buf[5] = 1;			mode_buf[6] = 0x04; /* WCE */			mode_buf_length = 7;			if (mode_buf_length > scsicmd->cmnd[4])				mode_buf_length = scsicmd->cmnd[4];		}		aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length);		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;		scsicmd->scsi_done(scsicmd);		return 0;	}	case MODE_SENSE_10:	{		char mode_buf[11];		int mode_buf_length = 8;		dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n"));		mode_buf[0] = 0;	/* Mode data length (MSB) */		mode_buf[1] = 6;	/* Mode data length (LSB) */		mode_buf[2] = 0;	/* Medium type - default */		mode_buf[3] = 0;	/* Device-specific param,					   bit 8: 0/1 = write enabled/protected					   bit 4: 0/1 = FUA enabled */		if (dev->raw_io_interface)			mode_buf[3] = 0x10;		mode_buf[4] = 0;	/* reserved */		mode_buf[5] = 0;	/* reserved */		mode_buf[6] = 0;	/* Block descriptor length (MSB) */		mode_buf[7] = 0;	/* Block descriptor length (LSB) */		if (((scsicmd->cmnd[2] & 0x3f) == 8) ||		  ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) {			mode_buf[1] = 9;			mode_buf[8] = 8;			mode_buf[9] = 1;			mode_buf[10] = 0x04; /* WCE */			mode_buf_length = 11;			if (mode_buf_length > scsicmd->cmnd[8])				mode_buf_length = scsicmd->cmnd[8];		}		aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length);		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;		scsicmd->scsi_done(scsicmd);		return 0;	}	case REQUEST_SENSE:		dprintk((KERN_DEBUG "REQUEST SENSE command.\n"));		memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, sizeof (struct sense_data));		memset(&dev->fsa_dev[cid].sense_data, 0, sizeof (struct sense_data));		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;		scsicmd->scsi_done(scsicmd);		return 0;	case ALLOW_MEDIUM_REMOVAL:		dprintk((KERN_DEBUG "LOCK command.\n"));		if (scsicmd->cmnd[4])			fsa_dev_ptr[cid].locked = 1;		else			fsa_dev_ptr[cid].locked = 0;		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;		scsicmd->scsi_done(scsicmd);		return 0;	/*	 *	These commands are all No-Ops	 */	case TEST_UNIT_READY:	case RESERVE:	case RELEASE:	case REZERO_UNIT:	case REASSIGN_BLOCKS:	case SEEK_10:	case START_STOP:		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;		scsicmd->scsi_done(scsicmd);		return 0;	}	switch (scsicmd->cmnd[0]) 	{		case READ_6:		case READ_10:		case READ_12:		case READ_16:			if (dev->in_reset)				return -1;			/*			 *	Hack to keep track of ordinal number of the device that			 *	corresponds to a container. Needed to convert			 *	containers to /dev/sd device names			 */			 			if (scsicmd->request->rq_disk)

⌨️ 快捷键说明

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