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

📄 sbp2.c

📁 IEE1394 火线接口驱动 for linux
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* Login FIFO DMA */	scsi_id->login_response =		pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_login_response),				     &scsi_id->login_response_dma);	if (!scsi_id->login_response)		goto alloc_fail;	SBP2_DMA_ALLOC("consistent DMA region for login FIFO");	/* Query logins ORB DMA */	scsi_id->query_logins_orb =		pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_query_logins_orb),				     &scsi_id->query_logins_orb_dma);	if (!scsi_id->query_logins_orb)		goto alloc_fail;	SBP2_DMA_ALLOC("consistent DMA region for query logins ORB");	/* Query logins response DMA */	scsi_id->query_logins_response =		pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_query_logins_response),				     &scsi_id->query_logins_response_dma);	if (!scsi_id->query_logins_response)		goto alloc_fail;	SBP2_DMA_ALLOC("consistent DMA region for query logins response");	/* Reconnect ORB DMA */	scsi_id->reconnect_orb =		pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_reconnect_orb),				     &scsi_id->reconnect_orb_dma);	if (!scsi_id->reconnect_orb)		goto alloc_fail;	SBP2_DMA_ALLOC("consistent DMA region for reconnect ORB");	/* Logout ORB DMA */	scsi_id->logout_orb =		pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_logout_orb),				     &scsi_id->logout_orb_dma);	if (!scsi_id->logout_orb)		goto alloc_fail;	SBP2_DMA_ALLOC("consistent DMA region for logout ORB");	/* Login ORB DMA */	scsi_id->login_orb =		pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_login_orb),				     &scsi_id->login_orb_dma);	if (!scsi_id->login_orb) {alloc_fail:		if (scsi_id->query_logins_response) {			pci_free_consistent(hi->host->pdev,					    sizeof(struct sbp2_query_logins_response),					    scsi_id->query_logins_response,					    scsi_id->query_logins_response_dma);			SBP2_DMA_FREE("query logins response DMA");		}		if (scsi_id->query_logins_orb) {			pci_free_consistent(hi->host->pdev,					    sizeof(struct sbp2_query_logins_orb),					    scsi_id->query_logins_orb,					    scsi_id->query_logins_orb_dma);			SBP2_DMA_FREE("query logins ORB DMA");		}			if (scsi_id->logout_orb) {			pci_free_consistent(hi->host->pdev,					sizeof(struct sbp2_logout_orb),					scsi_id->logout_orb,					scsi_id->logout_orb_dma);			SBP2_DMA_FREE("logout ORB DMA");		}		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("reconnect ORB DMA");		}		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("login FIFO DMA");		}		kfree(scsi_id);		list_del(&scsi_id->list);		SBP2_ERR ("Could not allocate memory for scsi_id");		return -ENOMEM;	}	SBP2_DMA_ALLOC("consistent DMA region for login ORB");	/*	 * Find an empty spot to stick our scsi id instance data. 	 */	for (i = 0; i < hi->scsi_host->max_id; i++) {		if (!hi->scsi_id[i]) {			hi->scsi_id[i] = scsi_id;			scsi_id->id = i;			SBP2_DEBUG("New SBP-2 device inserted, SCSI ID = %x", (unsigned int) i);			break;		}	}	/*	 * Create our command orb pool	 */	if (sbp2util_create_command_orb_pool(scsi_id)) {		SBP2_ERR("sbp2util_create_command_orb_pool failed!");		sbp2_remove_device(scsi_id);		return -ENOMEM;	}	/*	 * Make sure we are not out of space	 */	if (i == hi->scsi_host->max_id) {		SBP2_ERR("No slots left for SBP-2 device");		sbp2_remove_device(scsi_id);		return -EBUSY;	}	/* Schedule a timeout here. The reason is that we may be so close	 * to a bus reset, that the device is not available for logins.	 * This can happen when the bus reset is caused by the host	 * connected to the sbp2 device being removed. That host would	 * have a certain amount of time to relogin before the sbp2 device	 * allows someone else to login instead. One second makes sense. */	set_current_state(TASK_INTERRUPTIBLE);	schedule_timeout(HZ);	/*	 * Login to the sbp-2 device	 */	if (sbp2_login_device(scsi_id)) {		/* Login failed, just remove the device. */		sbp2_remove_device(scsi_id);		return -EBUSY;	}	/*	 * Set max retries to something large on the device	 */	sbp2_set_busy_timeout(scsi_id);		/*	 * Do a SBP-2 fetch agent reset	 */	sbp2_agent_reset(scsi_id, 1);		/*	 * Get the max speed and packet size that we can use	 */	sbp2_max_speed_and_size(scsi_id);#ifdef SBP2_USE_SCSI_ADDREM_HACK	/* Try to hook ourselves into the SCSI subsystem */	if (scsi_add_single_device(hi->scsi_host, 0, scsi_id->id, 0))		SBP2_INFO("Unable to connect SBP-2 device into the SCSI subsystem");#endif	return 0;}/* * This function removes an sbp2 device from the sbp2scsi_host_info struct. */static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id){	struct sbp2scsi_host_info *hi = scsi_id->hi;	SBP2_DEBUG("sbp2_remove_device");	/* Complete any pending commands with selection timeout */	sbp2scsi_complete_all_commands(scsi_id, DID_NO_CONNECT);       				/* Clean up any other structures */	sbp2util_remove_command_orb_pool(scsi_id);	hi->scsi_id[scsi_id->id] = NULL;	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->logout_orb_dma);		SBP2_DMA_FREE("single logout orb");	}	if (scsi_id->query_logins_orb) {		pci_free_consistent(hi->host->pdev,				    sizeof(struct sbp2_query_logins_orb),				    scsi_id->query_logins_orb,				    scsi_id->query_logins_orb_dma);		SBP2_DMA_FREE("single query logins orb");	}	if (scsi_id->query_logins_response) {		pci_free_consistent(hi->host->pdev,				    sizeof(struct sbp2_query_logins_response),				    scsi_id->query_logins_response,				    scsi_id->query_logins_response_dma);		SBP2_DMA_FREE("single query logins data");	}	SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->id);	list_del(&scsi_id->list);	kfree(scsi_id);}#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA/* * This function deals with physical dma write requests (for adapters that do not support * physical dma in hardware). Mostly just here for debugging... */static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid, int destid, quadlet_t *data,                                     u64 addr, size_t length, u16 flags){        /*         * Manually put the data in the right place.         */        memcpy(bus_to_virt((u32)addr), data, length);	sbp2util_packet_dump(data, length, "sbp2 phys dma write by device", (u32)addr);        return(RCODE_COMPLETE);}/* * This function deals with physical dma read requests (for adapters that do not support * physical dma in hardware). Mostly just here for debugging... */static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, quadlet_t *data,                                    u64 addr, size_t length, u16 flags){        /*         * Grab data from memory and send a read response.         */        memcpy(data, bus_to_virt((u32)addr), length);	sbp2util_packet_dump(data, length, "sbp2 phys dma read by device", (u32)addr);        return(RCODE_COMPLETE);}#endif/************************************** * SBP-2 protocol related section **************************************//* * This function determines if we should convert scsi commands for a particular sbp2 device type */static __inline__ int sbp2_command_conversion_device_type(u8 device_type){	return (((device_type == TYPE_DISK) ||		 (device_type == TYPE_SDAD) ||		 (device_type == TYPE_ROM)) ? 1:0);}/* * This function queries the device for the maximum concurrent logins it * supports. */static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id){	struct sbp2scsi_host_info *hi = scsi_id->hi;	quadlet_t data[2];	int max_logins;	int active_logins;	SBP2_DEBUG("sbp2_query_logins");	scsi_id->query_logins_orb->reserved1 = 0x0;	scsi_id->query_logins_orb->reserved2 = 0x0;	scsi_id->query_logins_orb->query_response_lo = scsi_id->query_logins_response_dma;	scsi_id->query_logins_orb->query_response_hi = ORB_SET_NODE_ID(hi->host->node_id);	SBP2_DEBUG("sbp2_query_logins: query_response_hi/lo initialized");	scsi_id->query_logins_orb->lun_misc = ORB_SET_FUNCTION(QUERY_LOGINS_REQUEST);	scsi_id->query_logins_orb->lun_misc |= ORB_SET_NOTIFY(1);	if (scsi_id->sbp2_device_type_and_lun != SBP2_DEVICE_TYPE_LUN_UNINITIALIZED) {		scsi_id->query_logins_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_query_logins: lun_misc initialized");	scsi_id->query_logins_orb->reserved_resp_length =		ORB_SET_QUERY_LOGINS_RESP_LENGTH(sizeof(struct sbp2_query_logins_response));	SBP2_DEBUG("sbp2_query_logins: reserved_resp_length initialized");	scsi_id->query_logins_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO +						    SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->id);	scsi_id->query_logins_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) |						     SBP2_STATUS_FIFO_ADDRESS_HI);	SBP2_DEBUG("sbp2_query_logins: status FIFO initialized");	sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb));	SBP2_DEBUG("sbp2_query_logins: orb byte-swapped");	sbp2util_packet_dump(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb),			     "sbp2 query logins orb", scsi_id->query_logins_orb_dma);	memset(scsi_id->query_logins_response, 0, sizeof(struct sbp2_query_logins_response));	memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block));	SBP2_DEBUG("sbp2_query_logins: query_logins_response/status FIFO memset");	data[0] = ORB_SET_NODE_ID(hi->host->node_id);	data[1] = scsi_id->query_logins_orb_dma;	sbp2util_cpu_to_be32_buffer(data, 8);	atomic_set(&scsi_id->sbp2_login_complete, 0);	SBP2_DEBUG("sbp2_query_logins: prepared to write");	hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8);	SBP2_DEBUG("sbp2_query_logins: written");	if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 2*HZ)) {		SBP2_ERR("Error querying logins to SBP-2 device - timed out");		return(-EIO);	}	if (scsi_id->status_block.ORB_offset_lo != scsi_id->query_logins_orb_dma) {		SBP2_ERR("Error querying logins to SBP-2 device - timed out");		return(-EIO);	}	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 querying logins to SBP-2 device - timed out");		return(-EIO);	}	sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_response, sizeof(struct sbp2_query_logins_response));	SBP2_DEBUG("length_max_logins = %x",		   (unsigned int)scsi_id->query_logins_response->length_max_logins);	SBP2_INFO("Query logins to SBP-2 device successful");	max_logins = RESPONSE_GET_MAX_LOGINS(scsi_id->query_logins_response->length_max_logins);	SBP2_INFO("Maximum concurrent logins supported: %d", max_logins);                                                                                	active_logins = RESPONSE_GET_ACTIVE_LOGINS(scsi_id->query_logins_response->length_max_logins);	SBP2_INFO("Number of active logins: %d", active_logins);                                                                                	if (active_logins >= max_logins) {		return(-EIO);	}                                                                                	return 0;}/* * This function is called in order to login to a particular SBP-2 device, * after a bus reset. */static int sbp2_login_device(struct scsi_id_instance_data *scsi_id) {	struct sbp2scsi_host_info *hi = scsi_id->hi;	quadlet_t data[2];	SBP2_DEBUG("sbp2_login_device");	if (!scsi_id->login_orb) {		SBP2_DEBUG("sbp2_login_device: login_orb not alloc'd!");		return(-EIO);	}	if (!sbp2_exclusive_login) {		if (sbp2_query_logins(scsi_id)) {			SBP2_ERR("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;	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(sbp2_exclusive_login);	/* Exclusive access to device */	scsi_id->login_orb->lun_misc |= ORB_SET_NOTIFY(1);	/* Notify us of login complete */	/* Set the lun if we were able to pull it from the device's unit directory */

⌨️ 快捷键说明

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