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

📄 sbp2.c

📁 Armlinux ieee1394接口驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
	/*	 * Do a SBP-2 fetch agent reset	 */	sbp2_agent_reset(hi, scsi_id, 0);		/*	 * Get the max speed and packet size that we can use	 */	sbp2_max_speed_and_size(hi, scsi_id);	return 0;}/* * This function removes an sbp2 device from the sbp2scsi_host_info struct. */static void sbp2_remove_device(struct sbp2scsi_host_info *hi, 			       struct scsi_id_instance_data *scsi_id){	SBP2_DEBUG("sbp2_remove_device");	/* Complete any pending commands with selection timeout */	sbp2scsi_complete_all_commands(hi, scsi_id, DID_NO_CONNECT);       				/* Clean up any other structures */	if (scsi_id->sbp2_total_command_orbs) {		sbp2util_remove_command_orb_pool(scsi_id, hi);	}	if (scsi_id->login_response) {		pci_free_consistent(hi->host->pdev,				    sizeof(struct sbp2_login_response),				    scsi_id->login_response,				    scsi_id->login_response_dma);		SBP2_DMA_FREE("single login FIFO");	}	if (scsi_id->login_orb) {		pci_free_consistent(hi->host->pdev,				    sizeof(struct sbp2_login_orb),				    scsi_id->login_orb,				    scsi_id->login_orb_dma);		SBP2_DMA_FREE("single login ORB");	}	if (scsi_id->reconnect_orb) {		pci_free_consistent(hi->host->pdev,				    sizeof(struct sbp2_reconnect_orb),				    scsi_id->reconnect_orb,				    scsi_id->reconnect_orb_dma);		SBP2_DMA_FREE("single reconnect orb");	}	if (scsi_id->logout_orb) {		pci_free_consistent(hi->host->pdev,				    sizeof(struct sbp2_logout_orb),				    scsi_id->logout_orb,				    scsi_id->reconnect_orb_dma);		SBP2_DMA_FREE("single logout orb");	}	SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->id);	hi->scsi_id[scsi_id->id] = NULL;	kfree(scsi_id);}/************************************** * SBP-2 protocol related section **************************************//* * This function is called in order to login to a particular SBP-2 device, * after a bus reset. */static int sbp2_login_device(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id) {	quadlet_t data[2];	unsigned long flags;	SBP2_DEBUG("sbp2_login_device");	if (!scsi_id->login_orb) {		SBP2_DEBUG("sbp2_login_device: login_orb not alloc'd!");		return(-EIO);	}	/* Set-up login ORB, assume no password */	scsi_id->login_orb->password_hi = 0; 	scsi_id->login_orb->password_lo = 0;	SBP2_DEBUG("sbp2_login_device: password_hi/lo initialized");	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);	SBP2_DEBUG("sbp2_login_device: login_response_hi/lo initialized");	scsi_id->login_orb->lun_misc = ORB_SET_FUNCTION(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(1);	/* Exclusive access to device */	scsi_id->login_orb->lun_misc |= ORB_SET_NOTIFY(1);		/* Notify us of login complete */	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;	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");	/*	 * 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);	SBP2_DEBUG("sbp2_login_device: prepared to write");	hpsb_write(hi->host, LOCAL_BUS | scsi_id->ne->nodeid, scsi_id->sbp2_management_agent_addr, data, 8);	SBP2_DEBUG("sbp2_login_device: written");	/*	 * Wait for login status... but, only if the device has not	 * already logged-in (some devices are fast)	 */	save_flags(flags);	cli();	/* 10 second timeout */	if (scsi_id->status_block.ORB_offset_lo != scsi_id->login_orb_dma)		sleep_on_timeout(&scsi_id->sbp2_login_wait, 10*HZ);	restore_flags(flags);	SBP2_DEBUG("sbp2_login_device: initial check");	/*	 * Match status to the login orb. If they do not match, it's	 * probably because the login timed-out.	 */	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);	}	SBP2_DEBUG("sbp2_login_device: second check");	/*	 * 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 sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id) {	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;	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));	/*	 * 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);	hpsb_write(hi->host, LOCAL_BUS | scsi_id->ne->nodeid, scsi_id->sbp2_management_agent_addr, data, 8);	/* Wait for device to logout...1 second. */	sleep_on_timeout(&scsi_id->sbp2_login_wait, HZ);	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 sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id) {	quadlet_t data[2];	unsigned long flags;	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;	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));	/*	 * 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);	hpsb_write(hi->host, LOCAL_BUS | scsi_id->ne->nodeid, scsi_id->sbp2_management_agent_addr, data, 8);	/*	 * Wait for reconnect status... but, only if the device has not	 * already reconnected (some devices are fast).	 */	save_flags(flags);	cli();	/* One second timout */	if (scsi_id->status_block.ORB_offset_lo != scsi_id->reconnect_orb_dma)		sleep_on_timeout(&scsi_id->sbp2_login_wait, HZ);	restore_flags(flags);	/*	 * Match status to the reconnect orb. If they do not match, it's	 * probably because the reconnect timed-out.	 */	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 sbp2scsi_host_info *hi, 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_write(hi->host, LOCAL_BUS | scsi_id->ne->nodeid, 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_instance_data *scsi_id){	struct unit_directory *ud;	int i;	SBP2_DEBUG("sbp2_parse_unit_directory");	ud = scsi_id->ud;	/* Handle different fields in the unit directory, based on keys */	for (i = 0; i < ud->arb_count; i++) {		switch (ud->arb_keys[i]) {		case SBP2_CSR_OFFSET_KEY:			/* Save off the management agent address */			scsi_id->sbp2_management_agent_addr =				CONFIG_ROM_INITIAL_MEMORY_SPACE + 				(ud->arb_values[i] << 2);			SBP2_DEBUG("sbp2_management_agent_addr = %x",				   (unsigned int) scsi_id->sbp2_management_agent_addr);			break;		case SBP2_COMMAND_SET_SPEC_ID_KEY:			/* Command spec organization */			scsi_id->sbp2_command_set_spec_id = ud->arb_values[i];			SBP2_DEBUG("sbp2_command_set_spec_id = %x",				   (unsigned int) scsi_id->sbp2_command_set_spec_id);			break;		case SBP2_COMMAND_SET_KEY:			/* Command set used by sbp2 device */			scsi_id->sbp2_command_set = ud->arb_values[i];			SBP2_DEBUG("sbp2_command_set = %x",				   (unsigned int) scsi_id->sbp2_command_set);			break;		case SBP2_UNIT_CHARACTERISTICS_KEY:			/*			 * Unit characterisitcs (orb related stuff			 * that I'm not yet paying attention to)			 */			scsi_id->sbp2_unit_characteristics = ud->arb_values[i];			SBP2_DEBUG("sbp2_unit_characteristics = %x",

⌨️ 快捷键说明

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