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

📄 sbp2.c

📁 这是关于ieee1394的最新源码,上面包含了所有更新的部分!
💻 C
📖 第 1 页 / 共 5 页
字号:
			goto failed_alloc;		}		SBP2_DEBUG("sbp2_alloc_device: allocated hostinfo");		hi->host = ud->ne->host;		INIT_LIST_HEAD(&hi->scsi_ids);#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA		/* Handle data movement if physical dma is not		 * enabled or not supported on host controller */		if (!hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host,					     &sbp2_physdma_ops,					     0x0ULL, 0xfffffffcULL)) {			SBP2_ERR("failed to register lower 4GB address range");			goto failed_alloc;		}#endif	}	/* Prevent unloading of the 1394 host */	if (!try_module_get(hi->host->driver->owner)) {		SBP2_ERR("failed to get a reference on 1394 host driver");		goto failed_alloc;	}	scsi_id->hi = hi;	list_add_tail(&scsi_id->scsi_list, &hi->scsi_ids);	/* Register the status FIFO address range. We could use the same FIFO	 * for targets at different nodes. However we need different FIFOs per	 * target in order to support multi-unit devices.	 * The FIFO is located out of the local host controller's physical range	 * but, if possible, within the posted write area. Status writes will	 * then be performed as unified transactions. This slightly reduces	 * bandwidth usage, and some Prolific based devices seem to require it.	 */	scsi_id->status_fifo_addr = hpsb_allocate_and_register_addrspace(			&sbp2_highlevel, ud->ne->host, &sbp2_ops,			sizeof(struct sbp2_status_block), sizeof(quadlet_t),			ud->ne->host->low_addr_space, CSR1212_ALL_SPACE_END);	if (scsi_id->status_fifo_addr == CSR1212_INVALID_ADDR_SPACE) {		SBP2_ERR("failed to allocate status FIFO address range");		goto failed_alloc;	}	/* Register our host with the SCSI stack. */	scsi_host = scsi_host_alloc(&scsi_driver_template,				    sizeof(unsigned long));	if (!scsi_host) {		SBP2_ERR("failed to register scsi host");		goto failed_alloc;	}	scsi_host->hostdata[0] = (unsigned long)scsi_id;	if (!scsi_add_host(scsi_host, &ud->device)) {		scsi_id->scsi_host = scsi_host;		return scsi_id;	}	SBP2_ERR("failed to add scsi host");	scsi_host_put(scsi_host);failed_alloc:	sbp2_remove_device(scsi_id);	return NULL;}static void sbp2_host_reset(struct hpsb_host *host){	struct sbp2scsi_host_info *hi;	struct scsi_id_instance_data *scsi_id;	hi = hpsb_get_hostinfo(&sbp2_highlevel, host);	if (!hi)		return;	list_for_each_entry(scsi_id, &hi->scsi_ids, scsi_list)		if (likely(atomic_read(&scsi_id->state) !=			   SBP2LU_STATE_IN_SHUTDOWN)) {			atomic_set(&scsi_id->state, SBP2LU_STATE_IN_RESET);			scsi_block_requests(scsi_id->scsi_host);		}}/* * This function is where we first pull the node unique ids, and then * allocate memory and register a SBP-2 device. */static int sbp2_start_device(struct scsi_id_instance_data *scsi_id){	struct sbp2scsi_host_info *hi = scsi_id->hi;	int error;	SBP2_DEBUG_ENTER();	/* 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)		goto alloc_fail;	SBP2_DMA_ALLOC("consistent DMA region for login ORB");	SBP2_DEBUG("New SBP-2 device inserted, SCSI ID = %x", scsi_id->ud->id);	/*	 * 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;	}	/* 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. */	if (msleep_interruptible(1000)) {		sbp2_remove_device(scsi_id);		return -EINTR;	}	/*	 * 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);	/* Add this device to the scsi layer now */	error = scsi_add_device(scsi_id->scsi_host, 0, scsi_id->ud->id, 0);	if (error) {		SBP2_ERR("scsi_add_device failed");		sbp2_logout_device(scsi_id);		sbp2_remove_device(scsi_id);		return error;	}	return 0;alloc_fail:	SBP2_ERR("Could not allocate memory for scsi_id");	sbp2_remove_device(scsi_id);	return -ENOMEM;}/* * 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;	SBP2_DEBUG_ENTER();	if (!scsi_id)		return;	hi = scsi_id->hi;	/* This will remove our scsi device aswell */	if (scsi_id->scsi_host) {		scsi_remove_host(scsi_id->scsi_host);		scsi_host_put(scsi_id->scsi_host);	}	flush_scheduled_work();	sbp2util_remove_command_orb_pool(scsi_id);	list_del(&scsi_id->scsi_list);	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");	}	if (scsi_id->status_fifo_addr != CSR1212_INVALID_ADDR_SPACE)		hpsb_unregister_addrspace(&sbp2_highlevel, hi->host,					  scsi_id->status_fifo_addr);	scsi_id->ud->device.driver_data = NULL;	if (hi)		module_put(hi->host->driver->owner);	SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->ud->id);	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 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_ENTER();	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);	scsi_id->query_logins_orb->lun_misc = ORB_SET_FUNCTION(SBP2_QUERY_LOGINS_REQUEST);	scsi_id->query_logins_orb->lun_misc |= ORB_SET_NOTIFY(1);	scsi_id->query_logins_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_lun);	scsi_id->query_logins_orb->reserved_resp_length =		ORB_SET_QUERY_LOGINS_RESP_LENGTH(sizeof(struct sbp2_query_logins_response));	scsi_id->query_logins_orb->status_fifo_hi =		ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id);	scsi_id->query_logins_orb->status_fifo_lo =		ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr);	sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb));	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));	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);	hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8);	if (sbp2util_access_timeout(scsi_id, 2*HZ)) {		SBP2_INFO("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_INFO("Error querying logins to SBP-2 device - timed out");		return -EIO;	}	if (STATUS_TEST_RDS(scsi_id->status_block.ORB_offset_hi_misc)) {		SBP2_INFO("Error querying logins to SBP-2 device - failed");		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);	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_ENTER();

⌨️ 快捷键说明

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