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

📄 sbp2.c

📁 ieee1394驱动,不多说了!直接可以在linux2.6内核中使用
💻 C
📖 第 1 页 / 共 5 页
字号:
	sense_data[4] = sbp2_status[13];	sense_data[5] = sbp2_status[14];	sense_data[6] = sbp2_status[15];	sense_data[7] = 10;	sense_data[8] = sbp2_status[16];	sense_data[9] = sbp2_status[17];	sense_data[10] = sbp2_status[18];	sense_data[11] = sbp2_status[19];	sense_data[12] = sbp2_status[10];	sense_data[13] = sbp2_status[11];	sense_data[14] = sbp2_status[20];	sense_data[15] = sbp2_status[21];	return sbp2_status[8] & 0x3f;}static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid,				    int destid, quadlet_t *data, u64 addr,				    size_t length, u16 fl){	struct sbp2_fwhost_info *hi;	struct sbp2_lu *lu = NULL, *lu_tmp;	struct scsi_cmnd *SCpnt = NULL;	struct sbp2_status_block *sb;	u32 scsi_status = SBP2_SCSI_STATUS_GOOD;	struct sbp2_command_info *cmd;	unsigned long flags;	if (unlikely(length < 8 || length > sizeof(struct sbp2_status_block))) {		SBP2_ERR("Wrong size of status block");		return RCODE_ADDRESS_ERROR;	}	if (unlikely(!host)) {		SBP2_ERR("host is NULL - this is bad!");		return RCODE_ADDRESS_ERROR;	}	hi = hpsb_get_hostinfo(&sbp2_highlevel, host);	if (unlikely(!hi)) {		SBP2_ERR("host info is NULL - this is bad!");		return RCODE_ADDRESS_ERROR;	}	/* Find the unit which wrote the status. */	list_for_each_entry(lu_tmp, &hi->logical_units, lu_list) {		if (lu_tmp->ne->nodeid == nodeid &&		    lu_tmp->status_fifo_addr == addr) {			lu = lu_tmp;			break;		}	}	if (unlikely(!lu)) {		SBP2_ERR("lu is NULL - device is gone?");		return RCODE_ADDRESS_ERROR;	}	/* Put response into lu status fifo buffer. The first two bytes	 * come in big endian bit order. Often the target writes only a	 * truncated status block, minimally the first two quadlets. The rest	 * is implied to be zeros. */	sb = &lu->status_block;	memset(sb->command_set_dependent, 0, sizeof(sb->command_set_dependent));	memcpy(sb, data, length);	sbp2util_be32_to_cpu_buffer(sb, 8);	/* Ignore unsolicited status. Handle command ORB status. */	if (unlikely(STATUS_GET_SRC(sb->ORB_offset_hi_misc) == 2))		cmd = NULL;	else		cmd = sbp2util_find_command_for_orb(lu, sb->ORB_offset_lo);	if (cmd) {		dma_sync_single_for_cpu(hi->host->device.parent,					cmd->command_orb_dma,					sizeof(struct sbp2_command_orb),					DMA_TO_DEVICE);		dma_sync_single_for_cpu(hi->host->device.parent, cmd->sge_dma,					sizeof(cmd->scatter_gather_element),					DMA_BIDIRECTIONAL);		/* Grab SCSI command pointers and check status. */		/*		 * FIXME: If the src field in the status is 1, the ORB DMA must		 * not be reused until status for a subsequent ORB is received.		 */		SCpnt = cmd->Current_SCpnt;		spin_lock_irqsave(&lu->cmd_orb_lock, flags);		sbp2util_mark_command_completed(lu, cmd);		spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);		if (SCpnt) {			u32 h = sb->ORB_offset_hi_misc;			u32 r = STATUS_GET_RESP(h);			if (r != RESP_STATUS_REQUEST_COMPLETE) {				SBP2_INFO("resp 0x%x, sbp_status 0x%x",					  r, STATUS_GET_SBP_STATUS(h));				scsi_status =					r == RESP_STATUS_TRANSPORT_FAILURE ?					SBP2_SCSI_STATUS_BUSY :					SBP2_SCSI_STATUS_COMMAND_TERMINATED;			}			if (STATUS_GET_LEN(h) > 1)				scsi_status = sbp2_status_to_sense_data(					(unchar *)sb, SCpnt->sense_buffer);			if (STATUS_TEST_DEAD(h))                                sbp2_agent_reset(lu, 0);		}		/* Check here to see if there are no commands in-use. If there		 * are none, we know that the fetch agent left the active state		 * _and_ that we did not reactivate it yet. Therefore clear		 * last_orb so that next time we write directly to the		 * ORB_POINTER register. That way the fetch agent does not need		 * to refetch the next_ORB. */		spin_lock_irqsave(&lu->cmd_orb_lock, flags);		if (list_empty(&lu->cmd_orb_inuse))			lu->last_orb = NULL;		spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);	} else {		/* It's probably status after a management request. */		if ((sb->ORB_offset_lo == lu->reconnect_orb_dma) ||		    (sb->ORB_offset_lo == lu->login_orb_dma) ||		    (sb->ORB_offset_lo == lu->query_logins_orb_dma) ||		    (sb->ORB_offset_lo == lu->logout_orb_dma)) {			lu->access_complete = 1;			wake_up_interruptible(&sbp2_access_wq);		}	}	if (SCpnt)		sbp2scsi_complete_command(lu, scsi_status, SCpnt,					  cmd->Current_done);	return RCODE_COMPLETE;}/************************************** * SCSI interface related section **************************************/static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,				 void (*done)(struct scsi_cmnd *)){	struct sbp2_lu *lu = (struct sbp2_lu *)SCpnt->device->host->hostdata[0];	struct sbp2_fwhost_info *hi;	int result = DID_NO_CONNECT << 16;	if (unlikely(!sbp2util_node_is_available(lu)))		goto done;	hi = lu->hi;	if (unlikely(!hi)) {		SBP2_ERR("sbp2_fwhost_info is NULL - this is bad!");		goto done;	}	/* Multiple units are currently represented to the SCSI core as separate	 * targets, not as one target with multiple LUs. Therefore return	 * selection time-out to any IO directed at non-zero LUNs. */	if (unlikely(SCpnt->device->lun))		goto done;	if (unlikely(!hpsb_node_entry_valid(lu->ne))) {		SBP2_ERR("Bus reset in progress - rejecting command");		result = DID_BUS_BUSY << 16;		goto done;	}	/* Bidirectional commands are not yet implemented,	 * and unknown transfer direction not handled. */	if (unlikely(SCpnt->sc_data_direction == DMA_BIDIRECTIONAL)) {		SBP2_ERR("Cannot handle DMA_BIDIRECTIONAL - rejecting command");		result = DID_ERROR << 16;		goto done;	}	if (sbp2_send_command(lu, SCpnt, done)) {		SBP2_ERR("Error sending SCSI command");		sbp2scsi_complete_command(lu,					  SBP2_SCSI_STATUS_SELECTION_TIMEOUT,					  SCpnt, done);	}	return 0;done:	SCpnt->result = result;	done(SCpnt);	return 0;}static void sbp2scsi_complete_all_commands(struct sbp2_lu *lu, u32 status){	struct sbp2_fwhost_info *hi = lu->hi;	struct list_head *lh;	struct sbp2_command_info *cmd;	unsigned long flags;	spin_lock_irqsave(&lu->cmd_orb_lock, flags);	while (!list_empty(&lu->cmd_orb_inuse)) {		lh = lu->cmd_orb_inuse.next;		cmd = list_entry(lh, struct sbp2_command_info, list);		dma_sync_single_for_cpu(hi->host->device.parent,				        cmd->command_orb_dma,					sizeof(struct sbp2_command_orb),					DMA_TO_DEVICE);		dma_sync_single_for_cpu(hi->host->device.parent, cmd->sge_dma,					sizeof(cmd->scatter_gather_element),					DMA_BIDIRECTIONAL);		sbp2util_mark_command_completed(lu, cmd);		if (cmd->Current_SCpnt) {			cmd->Current_SCpnt->result = status << 16;			cmd->Current_done(cmd->Current_SCpnt);		}	}	spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);	return;}/* * Complete a regular SCSI command. Can be called in atomic context. */static void sbp2scsi_complete_command(struct sbp2_lu *lu, u32 scsi_status,				      struct scsi_cmnd *SCpnt,				      void (*done)(struct scsi_cmnd *)){	if (!SCpnt) {		SBP2_ERR("SCpnt is NULL");		return;	}	switch (scsi_status) {	case SBP2_SCSI_STATUS_GOOD:		SCpnt->result = DID_OK << 16;		break;	case SBP2_SCSI_STATUS_BUSY:		SBP2_ERR("SBP2_SCSI_STATUS_BUSY");		SCpnt->result = DID_BUS_BUSY << 16;		break;	case SBP2_SCSI_STATUS_CHECK_CONDITION:		SCpnt->result = CHECK_CONDITION << 1 | DID_OK << 16;		break;	case SBP2_SCSI_STATUS_SELECTION_TIMEOUT:		SBP2_ERR("SBP2_SCSI_STATUS_SELECTION_TIMEOUT");		SCpnt->result = DID_NO_CONNECT << 16;		scsi_print_command(SCpnt);		break;	case SBP2_SCSI_STATUS_CONDITION_MET:	case SBP2_SCSI_STATUS_RESERVATION_CONFLICT:	case SBP2_SCSI_STATUS_COMMAND_TERMINATED:		SBP2_ERR("Bad SCSI status = %x", scsi_status);		SCpnt->result = DID_ERROR << 16;		scsi_print_command(SCpnt);		break;	default:		SBP2_ERR("Unsupported SCSI status = %x", scsi_status);		SCpnt->result = DID_ERROR << 16;	}	/* If a bus reset is in progress and there was an error, complete	 * the command as busy so that it will get retried. */	if (!hpsb_node_entry_valid(lu->ne)	    && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {		SBP2_ERR("Completing command with busy (bus reset)");		SCpnt->result = DID_BUS_BUSY << 16;	}	/* Tell the SCSI stack that we're done with this command. */	done(SCpnt);}static int sbp2scsi_slave_alloc(struct scsi_device *sdev){	struct sbp2_lu *lu = (struct sbp2_lu *)sdev->host->hostdata[0];	lu->sdev = sdev;	sdev->allow_restart = 1;	if (lu->workarounds & SBP2_WORKAROUND_INQUIRY_36)		sdev->inquiry_len = 36;	return 0;}static int sbp2scsi_slave_configure(struct scsi_device *sdev){	struct sbp2_lu *lu = (struct sbp2_lu *)sdev->host->hostdata[0];	sdev->use_10_for_rw = 1;	if (sdev->type == TYPE_ROM)		sdev->use_10_for_ms = 1;	if (sdev->type == TYPE_DISK &&	    lu->workarounds & SBP2_WORKAROUND_MODE_SENSE_8)		sdev->skip_ms_page_8 = 1;	if (lu->workarounds & SBP2_WORKAROUND_FIX_CAPACITY)		sdev->fix_capacity = 1;	return 0;}static void sbp2scsi_slave_destroy(struct scsi_device *sdev){	((struct sbp2_lu *)sdev->host->hostdata[0])->sdev = NULL;	return;}/* * Called by scsi stack when something has really gone wrong. * Usually called when a command has timed-out for some reason. */static int sbp2scsi_abort(struct scsi_cmnd *SCpnt){	struct sbp2_lu *lu = (struct sbp2_lu *)SCpnt->device->host->hostdata[0];	struct sbp2_fwhost_info *hi = lu->hi;	struct sbp2_command_info *cmd;	unsigned long flags;	SBP2_INFO("aborting sbp2 command");	scsi_print_command(SCpnt);	if (sbp2util_node_is_available(lu)) {		sbp2_agent_reset(lu, 1);		/* Return a matching command structure to the free pool. */		spin_lock_irqsave(&lu->cmd_orb_lock, flags);		cmd = sbp2util_find_command_for_SCpnt(lu, SCpnt);		if (cmd) {			dma_sync_single_for_cpu(hi->host->device.parent,					cmd->command_orb_dma,					sizeof(struct sbp2_command_orb),					DMA_TO_DEVICE);			dma_sync_single_for_cpu(hi->host->device.parent,					cmd->sge_dma,					sizeof(cmd->scatter_gather_element),					DMA_BIDIRECTIONAL);			sbp2util_mark_command_completed(lu, cmd);			if (cmd->Current_SCpnt) {				cmd->Current_SCpnt->result = DID_ABORT << 16;				cmd->Current_done(cmd->Current_SCpnt);			}		}		spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);		sbp2scsi_complete_all_commands(lu, DID_BUS_BUSY);	}	return SUCCESS;}/* * Called by scsi stack when something has really gone wrong. */static int sbp2scsi_reset(struct scsi_cmnd *SCpnt){	struct sbp2_lu *lu = (struct sbp2_lu *)SCpnt->device->host->hostdata[0];	SBP2_INFO("reset requested");	if (sbp2util_node_is_available(lu)) {		SBP2_INFO("generating sbp2 fetch agent reset");		sbp2_agent_reset(lu, 1);	}	return SUCCESS;}static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev,					   struct device_attribute *attr,					   char *buf){	struct scsi_device *sdev;	struct sbp2_lu *lu;	if (!(sdev = to_scsi_device(dev)))		return 0;	if (!(lu = (struct sbp2_lu *)sdev->host->hostdata[0]))		return 0;	return sprintf(buf, "%016Lx:%d:%d\n", (unsigned long long)lu->ne->guid,		       lu->ud->id, ORB_SET_LUN(lu->lun));}MODULE_AUTHOR("Ben Collins <bcollins@debian.org>");MODULE_DESCRIPTION("IEEE-1394 SBP-2 protocol driver");MODULE_SUPPORTED_DEVICE(SBP2_DEVICE_NAME);MODULE_LICENSE("GPL");static int sbp2_module_init(void){	int ret;	if (sbp2_serialize_io) {		sbp2_shost_template.can_queue = 1;		sbp2_shost_template.cmd_per_lun = 1;	}	if (sbp2_default_workarounds & SBP2_WORKAROUND_128K_MAX_TRANS &&	    (sbp2_max_sectors * 512) > (128 * 1024))		sbp2_max_sectors = 128 * 1024 / 512;	sbp2_shost_template.max_sectors = sbp2_max_sectors;	hpsb_register_highlevel(&sbp2_highlevel);	ret = hpsb_register_protocol(&sbp2_driver);	if (ret) {		SBP2_ERR("Failed to register protocol");		hpsb_unregister_highlevel(&sbp2_highlevel);		return ret;	}	return 0;}static void __exit sbp2_module_exit(void){	hpsb_unregister_protocol(&sbp2_driver);	hpsb_unregister_highlevel(&sbp2_highlevel);}module_init(sbp2_module_init);module_exit(sbp2_module_exit);

⌨️ 快捷键说明

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