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

📄 sbp2.c

📁 这是关于ieee1394的最新源码,上面包含了所有更新的部分!
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (!scsi_id->login_orb) {		SBP2_DEBUG("%s: login_orb not alloc'd!", __FUNCTION__);		return -EIO;	}	if (!exclusive_login) {		if (sbp2_query_logins(scsi_id)) {			SBP2_INFO("Device does not support any more concurrent logins");			return -EIO;		}	}	/* Set-up login ORB, assume no password */	scsi_id->login_orb->password_hi = 0;	scsi_id->login_orb->password_lo = 0;	scsi_id->login_orb->login_response_lo = scsi_id->login_response_dma;	scsi_id->login_orb->login_response_hi = ORB_SET_NODE_ID(hi->host->node_id);	scsi_id->login_orb->lun_misc = ORB_SET_FUNCTION(SBP2_LOGIN_REQUEST);	scsi_id->login_orb->lun_misc |= ORB_SET_RECONNECT(0);	/* One second reconnect time */	scsi_id->login_orb->lun_misc |= ORB_SET_EXCLUSIVE(exclusive_login);	/* Exclusive access to device */	scsi_id->login_orb->lun_misc |= ORB_SET_NOTIFY(1);	/* Notify us of login complete */	scsi_id->login_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_lun);	scsi_id->login_orb->passwd_resp_lengths =		ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response));	scsi_id->login_orb->status_fifo_hi =		ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);	scsi_id->login_orb->status_fifo_lo =		ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr);	sbp2util_cpu_to_be32_buffer(scsi_id->login_orb, sizeof(struct sbp2_login_orb));	sbp2util_packet_dump(scsi_id->login_orb, sizeof(struct sbp2_login_orb),			     "sbp2 login orb", scsi_id->login_orb_dma);	memset(scsi_id->login_response, 0, sizeof(struct sbp2_login_response));	data[0] = ORB_SET_NODE_ID(hi->host->node_id);	data[1] = scsi_id->login_orb_dma;	sbp2util_cpu_to_be32_buffer(data, 8);	hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8);	/*	 * Wait for login status (up to 20 seconds)...	 */	if (sbp2util_access_timeout(scsi_id, 20*HZ)) {		SBP2_ERR("Error logging into SBP-2 device - timed out");		return -EIO;	}	/*	 * Sanity. Make sure status returned matches login orb.	 */	if (scsi_id->status_block.ORB_offset_lo != scsi_id->login_orb_dma) {		SBP2_ERR("Error logging into SBP-2 device - timed out");		return -EIO;	}	if (STATUS_TEST_RDS(scsi_id->status_block.ORB_offset_hi_misc)) {		SBP2_ERR("Error logging into SBP-2 device - failed");		return -EIO;	}	/*	 * Byte swap the login response, for use when reconnecting or	 * logging out.	 */	sbp2util_cpu_to_be32_buffer(scsi_id->login_response, sizeof(struct sbp2_login_response));	/*	 * Grab our command block agent address from the login response.	 */	SBP2_DEBUG("command_block_agent_hi = %x",		   (unsigned int)scsi_id->login_response->command_block_agent_hi);	SBP2_DEBUG("command_block_agent_lo = %x",		   (unsigned int)scsi_id->login_response->command_block_agent_lo);	scsi_id->sbp2_command_block_agent_addr =		((u64)scsi_id->login_response->command_block_agent_hi) << 32;	scsi_id->sbp2_command_block_agent_addr |= ((u64)scsi_id->login_response->command_block_agent_lo);	scsi_id->sbp2_command_block_agent_addr &= 0x0000ffffffffffffULL;	SBP2_INFO("Logged into SBP-2 device");	return 0;}/* * This function is called in order to logout from a particular SBP-2 * device, usually called during driver unload. */static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id){	struct sbp2scsi_host_info *hi = scsi_id->hi;	quadlet_t data[2];	int error;	SBP2_DEBUG_ENTER();	/*	 * Set-up logout ORB	 */	scsi_id->logout_orb->reserved1 = 0x0;	scsi_id->logout_orb->reserved2 = 0x0;	scsi_id->logout_orb->reserved3 = 0x0;	scsi_id->logout_orb->reserved4 = 0x0;	scsi_id->logout_orb->login_ID_misc = ORB_SET_FUNCTION(SBP2_LOGOUT_REQUEST);	scsi_id->logout_orb->login_ID_misc |= ORB_SET_LOGIN_ID(scsi_id->login_response->length_login_ID);	/* Notify us when complete */	scsi_id->logout_orb->login_ID_misc |= ORB_SET_NOTIFY(1);	scsi_id->logout_orb->reserved5 = 0x0;	scsi_id->logout_orb->status_fifo_hi =		ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);	scsi_id->logout_orb->status_fifo_lo =		ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr);	/*	 * Byte swap ORB if necessary	 */	sbp2util_cpu_to_be32_buffer(scsi_id->logout_orb, sizeof(struct sbp2_logout_orb));	sbp2util_packet_dump(scsi_id->logout_orb, sizeof(struct sbp2_logout_orb),			     "sbp2 logout orb", scsi_id->logout_orb_dma);	/*	 * Ok, let's write to the target's management agent register	 */	data[0] = ORB_SET_NODE_ID(hi->host->node_id);	data[1] = scsi_id->logout_orb_dma;	sbp2util_cpu_to_be32_buffer(data, 8);	error = hpsb_node_write(scsi_id->ne,				scsi_id->sbp2_management_agent_addr, data, 8);	if (error)		return error;	/* Wait for device to logout...1 second. */	if (sbp2util_access_timeout(scsi_id, HZ))		return -EIO;	SBP2_INFO("Logged out of SBP-2 device");	return 0;}/* * This function is called in order to reconnect to a particular SBP-2 * device, after a bus reset. */static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id){	struct sbp2scsi_host_info *hi = scsi_id->hi;	quadlet_t data[2];	int error;	SBP2_DEBUG_ENTER();	/*	 * Set-up reconnect ORB	 */	scsi_id->reconnect_orb->reserved1 = 0x0;	scsi_id->reconnect_orb->reserved2 = 0x0;	scsi_id->reconnect_orb->reserved3 = 0x0;	scsi_id->reconnect_orb->reserved4 = 0x0;	scsi_id->reconnect_orb->login_ID_misc = ORB_SET_FUNCTION(SBP2_RECONNECT_REQUEST);	scsi_id->reconnect_orb->login_ID_misc |=		ORB_SET_LOGIN_ID(scsi_id->login_response->length_login_ID);	/* Notify us when complete */	scsi_id->reconnect_orb->login_ID_misc |= ORB_SET_NOTIFY(1);	scsi_id->reconnect_orb->reserved5 = 0x0;	scsi_id->reconnect_orb->status_fifo_hi =		ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);	scsi_id->reconnect_orb->status_fifo_lo =		ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr);	/*	 * Byte swap ORB if necessary	 */	sbp2util_cpu_to_be32_buffer(scsi_id->reconnect_orb, sizeof(struct sbp2_reconnect_orb));	sbp2util_packet_dump(scsi_id->reconnect_orb, sizeof(struct sbp2_reconnect_orb),			     "sbp2 reconnect orb", scsi_id->reconnect_orb_dma);	data[0] = ORB_SET_NODE_ID(hi->host->node_id);	data[1] = scsi_id->reconnect_orb_dma;	sbp2util_cpu_to_be32_buffer(data, 8);	error = hpsb_node_write(scsi_id->ne,				scsi_id->sbp2_management_agent_addr, data, 8);	if (error)		return error;	/*	 * Wait for reconnect status (up to 1 second)...	 */	if (sbp2util_access_timeout(scsi_id, HZ)) {		SBP2_ERR("Error reconnecting to SBP-2 device - timed out");		return -EIO;	}	/*	 * Sanity. Make sure status returned matches reconnect orb.	 */	if (scsi_id->status_block.ORB_offset_lo != scsi_id->reconnect_orb_dma) {		SBP2_ERR("Error reconnecting to SBP-2 device - timed out");		return -EIO;	}	if (STATUS_TEST_RDS(scsi_id->status_block.ORB_offset_hi_misc)) {		SBP2_ERR("Error reconnecting to SBP-2 device - failed");		return -EIO;	}	HPSB_DEBUG("Reconnected to SBP-2 device");	return 0;}/* * This function is called in order to set the busy timeout (number of * retries to attempt) on the sbp2 device. */static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id){	quadlet_t data;	SBP2_DEBUG_ENTER();	data = cpu_to_be32(SBP2_BUSY_TIMEOUT_VALUE);	if (hpsb_node_write(scsi_id->ne, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4))		SBP2_ERR("%s error", __FUNCTION__);	return 0;}/* * This function is called to parse sbp2 device's config rom unit * directory. Used to determine things like sbp2 management agent offset, * and command set used (SCSI or RBC). */static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,				      struct unit_directory *ud){	struct csr1212_keyval *kv;	struct csr1212_dentry *dentry;	u64 management_agent_addr;	u32 command_set_spec_id, command_set, unit_characteristics,	    firmware_revision;	unsigned workarounds;	int i;	SBP2_DEBUG_ENTER();	management_agent_addr = 0x0;	command_set_spec_id = 0x0;	command_set = 0x0;	unit_characteristics = 0x0;	firmware_revision = 0x0;	/* Handle different fields in the unit directory, based on keys */	csr1212_for_each_dir_entry(ud->ne->csr, kv, ud->ud_kv, dentry) {		switch (kv->key.id) {		case CSR1212_KV_ID_DEPENDENT_INFO:			if (kv->key.type == CSR1212_KV_TYPE_CSR_OFFSET) {				/* Save off the management agent address */				management_agent_addr =				    CSR1212_REGISTER_SPACE_BASE +				    (kv->value.csr_offset << 2);				SBP2_DEBUG("sbp2_management_agent_addr = %x",					   (unsigned int)management_agent_addr);			} else if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {				scsi_id->sbp2_lun =				    ORB_SET_LUN(kv->value.immediate);			}			break;		case SBP2_COMMAND_SET_SPEC_ID_KEY:			/* Command spec organization */			command_set_spec_id = kv->value.immediate;			SBP2_DEBUG("sbp2_command_set_spec_id = %x",				   (unsigned int)command_set_spec_id);			break;		case SBP2_COMMAND_SET_KEY:			/* Command set used by sbp2 device */			command_set = kv->value.immediate;			SBP2_DEBUG("sbp2_command_set = %x",				   (unsigned int)command_set);			break;		case SBP2_UNIT_CHARACTERISTICS_KEY:			/*			 * Unit characterisitcs (orb related stuff			 * that I'm not yet paying attention to)			 */			unit_characteristics = kv->value.immediate;			SBP2_DEBUG("sbp2_unit_characteristics = %x",				   (unsigned int)unit_characteristics);			break;		case SBP2_FIRMWARE_REVISION_KEY:			/* Firmware revision */			firmware_revision = kv->value.immediate;			SBP2_DEBUG("sbp2_firmware_revision = %x",				   (unsigned int)firmware_revision);			break;		default:			break;		}	}	workarounds = sbp2_default_workarounds;	if (!(workarounds & SBP2_WORKAROUND_OVERRIDE))		for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) {			if (sbp2_workarounds_table[i].firmware_revision &&			    sbp2_workarounds_table[i].firmware_revision !=			    (firmware_revision & 0xffff00))				continue;			if (sbp2_workarounds_table[i].model_id &&			    sbp2_workarounds_table[i].model_id != ud->model_id)				continue;			workarounds |= sbp2_workarounds_table[i].workarounds;			break;		}	if (workarounds)		SBP2_INFO("Workarounds for node " NODE_BUS_FMT ": 0x%x "			  "(firmware_revision 0x%06x, vendor_id 0x%06x,"			  " model_id 0x%06x)",			  NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid),			  workarounds, firmware_revision,			  ud->vendor_id ? ud->vendor_id : ud->ne->vendor_id,			  ud->model_id);	/* We would need one SCSI host template for each target to adjust	 * max_sectors on the fly, therefore warn only. */	if (workarounds & SBP2_WORKAROUND_128K_MAX_TRANS &&	    (max_sectors * 512) > (128 * 1024))		SBP2_WARN("Node " NODE_BUS_FMT ": Bridge only supports 128KB "			  "max transfer size. WARNING: Current max_sectors "			  "setting is larger than 128KB (%d sectors)",			  NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid),			  max_sectors);	/* If this is a logical unit directory entry, process the parent	 * to get the values. */	if (ud->flags & UNIT_DIRECTORY_LUN_DIRECTORY) {		struct unit_directory *parent_ud =			container_of(ud->device.parent, struct unit_directory, device);		sbp2_parse_unit_directory(scsi_id, parent_ud);	} else {		scsi_id->sbp2_management_agent_addr = management_agent_addr;		scsi_id->sbp2_command_set_spec_id = command_set_spec_id;		scsi_id->sbp2_command_set = command_set;		scsi_id->sbp2_unit_characteristics = unit_characteristics;		scsi_id->sbp2_firmware_revision = firmware_revision;		scsi_id->workarounds = workarounds;		if (ud->flags & UNIT_DIRECTORY_HAS_LUN)			scsi_id->sbp2_lun = ORB_SET_LUN(ud->lun);	}}#define SBP2_PAYLOAD_TO_BYTES(p) (1 << ((p) + 2))/* * This function is called in order to determine the max speed and packet * size we can use in our ORBs. Note, that we (the driver and host) only * initiate the transaction. The SBP-2 device actually transfers the data * (by reading from the DMA area we tell it). This means that the SBP-2 * device decides the actual maximum data it can transfer. We just tell it * the speed that it needs to use, and the max_rec the host supports, and * it takes care of the rest. */static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id){	struct sbp2scsi_host_info *hi = scsi_id->hi;	u8 payload;	SBP2_DEBUG_ENTER();	scsi_id->speed_code =	    hi->host->speed[NODEID_TO_NODE(scsi_id->ne->nodeid)];	/* Bump down our speed if the user requested it */	if (scsi_id->speed_code > max_speed) {		scsi_id->speed_code = max_speed;		SBP2_ERR("Forcing SBP-2 max speed down to %s",			 hpsb_speedto_str[scsi_id->speed_code]);	}	/* Payload size is the lesser of what our speed supports and what	 * our host supports.  */	payload = min(sbp2_speedto_max_payload[scsi_id->speed_code],		      (u8) (hi->host->csr.max_rec - 1));	/* If physical DMA is off, work around limitation in ohci1394:	 * packet size must not exceed PAGE_SIZE */	if (scsi_id->ne->host->low_addr_space < (1ULL << 32))		while (SBP2_PAYLOAD_TO_BYTES(payload) + 24 > PAGE_SIZE &&		       payload)			payload--;	HPSB_DEBUG("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [%u]",		   NODE_BUS_ARGS(hi->host, scsi_id->ne->nodeid),		   hpsb_speedto_str[scsi_id->speed_code],		   SBP2_PAYLOAD_TO_BYTES(payload));	scsi_id->max_payload_size = payload;	return 0;}/* * This function is called in order to perform a SBP-2 agent reset. */static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait){	quadlet_t data;

⌨️ 快捷键说明

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