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

📄 aachba.c

📁 h内核
💻 C
📖 第 1 页 / 共 4 页
字号:
			  (fib_callback) write_callback, 			  (void *) scsicmd);	}	/*	 *	Check that the command queued to the controller	 */	if (status == -EINPROGRESS)	{		dprintk("write queued.\n");		return 0;	}	printk(KERN_WARNING "aac_write: fib_send failed with status: %d\n", status);	/*	 *	For some reason, the Fib didn't queue, return QUEUE_FULL	 */	scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL;	aac_io_done(scsicmd);	fib_complete(cmd_fibcontext);	fib_free(cmd_fibcontext);	return 0;}static void synchronize_callback(void *context, struct fib *fibptr){	struct aac_synchronize_reply *synchronizereply;	struct scsi_cmnd *cmd;	cmd = context;	dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n", 				smp_processor_id(), jiffies));	BUG_ON(fibptr == NULL);	synchronizereply = fib_data(fibptr);	if (le32_to_cpu(synchronizereply->status) == CT_OK)		cmd->result = DID_OK << 16 | 			COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;	else {		struct scsi_device *sdev = cmd->device;		struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata;		u32 cid = ID_LUN_TO_CONTAINER(sdev->id, sdev->lun);		printk(KERN_WARNING 		     "synchronize_callback: synchronize failed, status = %d\n",		     synchronizereply->status);		cmd->result = DID_OK << 16 | 			COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;		set_sense((u8 *)&dev->fsa_dev[cid].sense_data,				    HARDWARE_ERROR,				    SENCODE_INTERNAL_TARGET_FAILURE,				    ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,				    0, 0);		memcpy(cmd->sense_buffer, &dev->fsa_dev[cid].sense_data,		  min(sizeof(dev->fsa_dev[cid].sense_data), 			  sizeof(cmd->sense_buffer)));	}	fib_complete(fibptr);	fib_free(fibptr);	aac_io_done(cmd);}static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid){	int status;	struct fib *cmd_fibcontext;	struct aac_synchronize *synchronizecmd;	struct scsi_cmnd *cmd;	struct scsi_device *sdev = scsicmd->device;	int active = 0;	unsigned long flags;	/*	 * Wait for all commands to complete to this specific	 * target (block).	 */	spin_lock_irqsave(&sdev->list_lock, flags);	list_for_each_entry(cmd, &sdev->cmd_list, list)		if (cmd != scsicmd && cmd->serial_number != 0) {			++active;			break;		}	spin_unlock_irqrestore(&sdev->list_lock, flags);	/*	 *	Yield the processor (requeue for later)	 */	if (active)		return SCSI_MLQUEUE_DEVICE_BUSY;	/*	 *	Alocate and initialize a Fib	 */	if (!(cmd_fibcontext = 	    fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata))) 		return SCSI_MLQUEUE_HOST_BUSY;	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(cid);	synchronizecmd->count = 	     cpu_to_le32(sizeof(((struct aac_synchronize_reply *)NULL)->data));	/*	 *	Now send the Fib to the adapter	 */	status = 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)		return 0;	printk(KERN_WARNING 		"aac_synchronize: fib_send failed with status: %d.\n", status);	fib_complete(cmd_fibcontext);	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 = 0;	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;	int cardtype = dev->cardtype;	int ret;		/*	 *	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.	 */	if (scsicmd->device->id != host->this_id) {		if ((scsicmd->device->channel == 0) ){			if( (scsicmd->device->id >= dev->maximum_num_containers) || (scsicmd->device->lun != 0)){ 				scsicmd->result = DID_NO_CONNECT << 16;				scsicmd->scsi_done(scsicmd);				return 0;			}			cid = ID_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun);			/*			 *	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 INQUIRY:				case READ_CAPACITY:				case TEST_UNIT_READY:					spin_unlock_irq(host->host_lock);					probe_container(dev, cid);					spin_lock_irq(host->host_lock);					if (fsa_dev_ptr[cid].valid == 0) {						scsicmd->result = DID_NO_CONNECT << 16;						scsicmd->scsi_done(scsicmd);						return 0;					}				default:					break;				}			}			/*			 *	If the target container still doesn't exist, 			 *	return failure			 */			if (fsa_dev_ptr[cid].valid == 0) {				scsicmd->result = DID_BAD_TARGET << 16;				scsicmd->scsi_done(scsicmd);				return 0;			}		} else {  /* check for physical non-dasd devices */			if(dev->nondasd_support == 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_ptr;		dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scsicmd->device->id));		inq_data_ptr = (struct inquiry_data *)scsicmd->request_buffer;		memset(inq_data_ptr, 0, sizeof (struct inquiry_data));		inq_data_ptr->inqd_ver = 2;	/* claim compliance to SCSI-2 */		inq_data_ptr->inqd_dtq = 0x80;	/* set RMB bit to one indicating that the medium is removable */		inq_data_ptr->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_ptr->inqd_len = 31;		/*Format for "pad2" is  RelAdr | WBus32 | WBus16 |  Sync  | Linked |Reserved| CmdQue | SftRe */		inq_data_ptr->inqd_pad2= 0x32 ;	 /*WBus16|Sync|CmdQue */		/*		 *	Set the Vendor, Product, and Revision Level		 *	see: <vendor>.c i.e. aac.c		 */		if (scsicmd->device->id == host->this_id) {			setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), (sizeof(container_types)/sizeof(char *)));			inq_data_ptr->inqd_pdt = INQD_PDT_PROC;	/* Processor device */			scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;			scsicmd->scsi_done(scsicmd);			return 0;		}		setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), fsa_dev_ptr[cid].type);		inq_data_ptr->inqd_pdt = INQD_PDT_DA;	/* Direct/random access device */		return aac_get_container_name(scsicmd, cid);	}	case READ_CAPACITY:	{		u32 capacity;		char *cp;		dprintk((KERN_DEBUG "READ CAPACITY command.\n"));		if (fsa_dev_ptr[cid].size <= 0x100000000LL)			capacity = fsa_dev_ptr[cid].size - 1;		else			capacity = (u32)-1;		cp = scsicmd->request_buffer;		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;		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;		scsicmd->scsi_done(scsicmd);		return 0;	}	case MODE_SENSE:	{		char *mode_buf;		dprintk((KERN_DEBUG "MODE SENSE command.\n"));		mode_buf = scsicmd->request_buffer;		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 */		mode_buf[3] = 0;	/* Block descriptor 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;		dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n"));		mode_buf = scsicmd->request_buffer;		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 */		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) */		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:			/*			 *	Hack to keep track of ordinal number of the device that			 *	corresponds to a container. Needed to convert			 *	containers to /dev/sd device names			 */			 			spin_unlock_irq(host->host_lock);			if  (scsicmd->request->rq_disk)				memcpy(fsa_dev_ptr[cid].devname,					scsicmd->request->rq_disk->disk_name,					8);			ret = aac_read(scsicmd, cid);			spin_lock_irq(host->host_lock);			return ret;		case WRITE_6:		case WRITE_10:			spin_unlock_irq(host->host_lock);			ret = aac_write(scsicmd, cid);			spin_lock_irq(host->host_lock);			return ret;		case SYNCHRONIZE_CACHE:			/* Issue FIB to tell Firmware to flush it's cache */			return aac_synchronize(scsicmd, cid);					default:			/*			 *	Unhandled commands			 */			printk(KERN_WARNING "Unhandled SCSI Command: 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;	}}static int query_disk(struct aac_dev *dev, void __user *arg){	struct aac_query_disk qd;	struct fsa_dev_info *fsa_dev_ptr;	fsa_dev_ptr = dev->fsa_dev;	if (copy_from_user(&qd, arg, sizeof (struct aac_query_disk)))		return -EFAULT;	if (qd.cnum == -1)		qd.cnum = ID_LUN_TO_CONTAINER(qd.id, qd.lun);	else if ((qd.bus == -1) && (qd.id == -1) && (qd.lun == -1)) 	{		if (qd.cnum < 0 || qd.cnum >= dev->maximum_num_containers)			return -EINVAL;		qd.instance = dev->scsi_host_ptr->host_no;		qd.bus = 0;		qd.id = CONTAINER_TO_ID(qd.cnum);		qd.lun = CONTAINER_TO_LUN(qd.cnum);	}	else return -EINVAL;	qd.valid = fsa_dev_ptr[qd.cnum].valid;	qd.locked = fsa_dev_ptr[qd.cnum].locked;	qd.deleted = fsa_dev_ptr[qd.cnum].deleted;	if (fsa_dev_ptr[qd.cnum].devname[0] == '\0')		qd.unmapped = 1;	else		qd.unmapped = 0;	strlcpy(qd.name, fsa_dev_ptr[qd.cnum].devname,	  min(sizeof(qd.name), sizeof(fsa_dev_ptr[qd.cnum].devname) + 1));	if (copy_to_user(arg, &qd, sizeof (struct aac_query_disk)))		return -EFAULT;	return 0;}static int force_delete_disk(struct aac_dev *dev, void __user *arg){	struct aac_delete_disk dd;	struct fsa_dev_info *fsa_dev_ptr;	fsa_dev_ptr = dev->fsa_dev;	if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk)))		return -EFAULT;	if (dd.cnum >= dev->maximum_num_containers)		return -EINVAL;	/*	 *	Mark this container as being deleted.	 */	fsa_dev_ptr[dd.cnum].deleted = 1;	/*	 *	Mark the container as no longer valid	 */	fsa_dev_ptr[dd.cnum].valid = 0;	return 0;}static int delete_disk(struct aac_dev *dev, void __user *arg){	struct aac_delete_disk dd;	struct fsa_dev_info *fsa_dev_ptr;	fsa_dev_ptr = dev->fsa_dev;	if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk)))		return -EFAULT;	if (dd.cnum >= dev->maximum_num_containers)		return -EINVAL;	/*	 *	If the container is locked, it can not be deleted by the API.	 */	if (fsa_dev_ptr[dd.cnum].locked)		return -EBUSY;	else {		/*		 *	Mark the container as no longer being valid.		 */		fsa_dev_ptr[dd.cnum].valid = 0;		fsa_dev_ptr[dd.cnum].devname[0] = '\0';		return 0;	}}int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg){	switch (cmd) {	case FSACTL_QUERY_DISK:		return query_disk(dev, arg);	case FSACTL_DELETE_DISK:		return delete_disk(dev, arg);	case FSACTL_FORCE_DELETE_DISK:		return force_delete_disk(dev, arg);	case FSACTL_GET_CONTAINERS:		return aac_get_containers(dev);	default:		return -ENOTTY;	}

⌨️ 快捷键说明

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