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

📄 sbp2.c

📁 IEE1394 火线接口驱动 for linux
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (scsi_id->sbp2_device_type_and_lun != SBP2_DEVICE_TYPE_LUN_UNINITIALIZED) {		scsi_id->login_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun);		SBP2_DEBUG("sbp2_query_logins: set lun to %d",			   ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun));	}	SBP2_DEBUG("sbp2_login_device: lun_misc initialized");	scsi_id->login_orb->passwd_resp_lengths =		ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response));	SBP2_DEBUG("sbp2_login_device: passwd_resp_lengths initialized");	scsi_id->login_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + 					     SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->id);	scsi_id->login_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) |					      SBP2_STATUS_FIFO_ADDRESS_HI);	SBP2_DEBUG("sbp2_login_device: status FIFO initialized");	/*	 * Byte swap ORB if necessary	 */	sbp2util_cpu_to_be32_buffer(scsi_id->login_orb, sizeof(struct sbp2_login_orb));	SBP2_DEBUG("sbp2_login_device: orb byte-swapped");	sbp2util_packet_dump(scsi_id->login_orb, sizeof(struct sbp2_login_orb), 			     "sbp2 login orb", scsi_id->login_orb_dma);	/*	 * Initialize login response and status fifo	 */	memset(scsi_id->login_response, 0, sizeof(struct sbp2_login_response));	memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block));	SBP2_DEBUG("sbp2_login_device: login_response/status FIFO memset");	/*	 * 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->login_orb_dma;	sbp2util_cpu_to_be32_buffer(data, 8);	atomic_set(&scsi_id->sbp2_login_complete, 0);	SBP2_DEBUG("sbp2_login_device: prepared to write to %08x",		   (unsigned int)scsi_id->sbp2_management_agent_addr);	hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8);	SBP2_DEBUG("sbp2_login_device: written");	/*	 * Wait for login status (up to 20 seconds)... 	 */	if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 20*HZ)) {		SBP2_ERR("Error logging into SBP-2 device - login 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 - login timed-out");		return(-EIO);	}	/*	 * Check status	 */	if (STATUS_GET_RESP(scsi_id->status_block.ORB_offset_hi_misc) ||	    STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) ||	    STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {		SBP2_ERR("Error logging into SBP-2 device - login 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];	SBP2_DEBUG("sbp2_logout_device");	/*	 * 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(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_lo = SBP2_STATUS_FIFO_ADDRESS_LO + 					      SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->id);	scsi_id->logout_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) |					       SBP2_STATUS_FIFO_ADDRESS_HI);	/*	 * 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);	atomic_set(&scsi_id->sbp2_login_complete, 0);	hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8);	/* Wait for device to logout...1 second. */	sbp2util_down_timeout(&scsi_id->sbp2_login_complete, HZ);	SBP2_INFO("Logged out of SBP-2 device");#ifdef SBP2_USE_SCSI_ADDREM_HACK	/* Now that we are logged out of the SBP-2 device, lets	 * try to un-hook ourselves from the SCSI subsystem */	if (scsi_remove_single_device(hi->scsi_host, 0, scsi_id->id, 0))		SBP2_INFO("Unable to disconnect SBP-2 device from the SCSI subsystem");#endif	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];	SBP2_DEBUG("sbp2_reconnect_device");	/*	 * 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(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_lo = SBP2_STATUS_FIFO_ADDRESS_LO + 						 SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->id);	scsi_id->reconnect_orb->status_FIFO_hi =		(ORB_SET_NODE_ID(hi->host->node_id) | SBP2_STATUS_FIFO_ADDRESS_HI);	/*	 * 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);	/*	 * Initialize status fifo	 */	memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block));	/*	 * 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->reconnect_orb_dma;	sbp2util_cpu_to_be32_buffer(data, 8);	atomic_set(&scsi_id->sbp2_login_complete, 0);	hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8);	/*	 * Wait for reconnect status (up to 1 second)...	 */	if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, HZ)) {		SBP2_ERR("Error reconnecting to SBP-2 device - reconnect 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 - reconnect timed-out");		return(-EIO);	}	/*	 * Check status	 */	if (STATUS_GET_RESP(scsi_id->status_block.ORB_offset_hi_misc) ||	    STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) ||	    STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {		SBP2_ERR("Error reconnecting to SBP-2 device - reconnect failed");		return(-EIO);	}	SBP2_INFO("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("sbp2_set_busy_timeout");	/*	 * Ok, let's write to the target's busy timeout register	 */	data = cpu_to_be32(SBP2_BUSY_TIMEOUT_VALUE);	if (hpsb_node_write(scsi_id->ne, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4)) {		SBP2_ERR("sbp2_set_busy_timeout error");	}	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_group *scsi_group,				      struct unit_directory *ud){	struct scsi_id_instance_data *scsi_id;	struct list_head *lh;	u64 management_agent_addr;	u32 command_set_spec_id, command_set, unit_characteristics,		firmware_revision, workarounds;	int i;	SBP2_DEBUG("sbp2_parse_unit_directory");	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 */	for (i = 0; i < ud->length; i++) {		switch (CONFIG_ROM_KEY(ud->quadlets[i])) {		case SBP2_CSR_OFFSET_KEY:			/* Save off the management agent address */			management_agent_addr =				CSR_REGISTER_BASE + 				(CONFIG_ROM_VALUE(ud->quadlets[i]) << 2);			SBP2_DEBUG("sbp2_management_agent_addr = %x",				   (unsigned int) management_agent_addr);			break;		case SBP2_COMMAND_SET_SPEC_ID_KEY:			/* Command spec organization */			command_set_spec_id				= CONFIG_ROM_VALUE(ud->quadlets[i]);			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 = CONFIG_ROM_VALUE(ud->quadlets[i]);			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				= CONFIG_ROM_VALUE(ud->quadlets[i]);			SBP2_DEBUG("sbp2_unit_characteristics = %x",				   (unsigned int) unit_characteristics);			break;		case SBP2_DEVICE_TYPE_AND_LUN_KEY:			/*			 * Device type and lun (used for			 * detemining type of sbp2 device)			 */			scsi_id = kmalloc(sizeof(*scsi_id), GFP_KERNEL);			if (!scsi_id) {				SBP2_ERR("Out of memory adding scsi_id, not all LUN's will be added");				break;			}			memset(scsi_id, 0, sizeof(*scsi_id));			scsi_id->sbp2_device_type_and_lun				= CONFIG_ROM_VALUE(ud->quadlets[i]);			SBP2_DEBUG("sbp2_device_type_and_lun = %x",				   (unsigned int) scsi_id->sbp2_device_type_and_lun);			list_add_tail(&scsi_id->list, &scsi_group->scsi_id_list);			break;		case SBP2_FIRMWARE_REVISION_KEY:			/* Firmware revision */			firmware_revision				= CONFIG_ROM_VALUE(ud->quadlets[i]);			if (sbp2_force_inquiry_hack)				SBP2_INFO("sbp2_firmware_revision = %x",				   (unsigned int) firmware_revision);			else	SBP2_DEBUG("sbp2_firmware_revision = %x",				   (unsigned int) firmware_revision);			break;		default:			break;		}	}	/* This is the start of our broken device checking. We try to hack	 * around oddities and known defects.  */	workarounds = 0x0;	/* If the vendor id is 0xa0b8 (Symbios vendor id), then we have a	 * bridge with 128KB max transfer size limitation. For sanity, we	 * only voice this when the current sbp2_max_sectors setting	 * exceeds the 128k limit. By default, that is not the case.	 *	 * It would be really nice if we could detect this before the scsi	 * host gets initialized. That way we can down-force the	 * sbp2_max_sectors to account for it. That is not currently	 * possible.  */	if ((firmware_revision & 0xffff00) ==			SBP2_128KB_BROKEN_FIRMWARE &&			(sbp2_max_sectors * 512) > (128 * 1024)) {		SBP2_WARN("Node " NODE_BUS_FMT ": Bridge only supports 128KB max transfer size.",				NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid));		SBP2_WARN("WARNING: Current sbp2_max_sectors setting is larger than 128KB (%d sectors)!",				sbp2_max_sectors);		workarounds |= SBP2_BREAKAGE_128K_MAX_TRANSFER;	}	/* Check for a blacklisted set of devices that require us to force	 * a 36 byte host inquiry. This can be overriden as a module param	 * (to force all hosts).  */	for (i = 0; i < NUM_BROKEN_INQUIRY_DEVS; i++) {		if ((firmware_revision & 0xffff00) ==				sbp2_broken_inquiry_list[i]) {			SBP2_WARN("Node " NODE_BUS_FMT ": Using 36byte inquiry workaround",					NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid));			workarounds |= SBP2_BREAKAGE_INQUIRY_HACK;			break; /* No need to continue. */		}	}	/* If this is a logical unit directory entry, process the parent	 * to get the common values. */	if (ud->flags & UNIT_DIRECTORY_LUN_DIRECTORY) {		sbp2_parse_unit_directory(scsi_group, ud->parent);	} else {		/* If our list is empty, add a base scsi_id (happens in a normal		 * case where there is no logical_unit_number entry */		if (list_empty(&scsi_group->scsi_id_list)) {			scsi_id = kmalloc(sizeof(*scsi_id), GFP_KERNEL);			if (!scsi_id) {				SBP2_ERR("Out of memory adding scsi_id");				return;			}			memset(scsi_id, 0, sizeof(*scsi_id));

⌨️ 快捷键说明

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