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

📄 sbp2.c

📁 这个是uClinux下的ieee1394驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
 */static void sbp2_add_host(struct hpsb_host *host){	struct sbp2scsi_host_info *hi;	unsigned long flags;	SBP2_DEBUG("sbp2_add_host");	/* Allocate some memory for our host info structure */	hi = (struct sbp2scsi_host_info *)kmalloc(sizeof(struct sbp2scsi_host_info),						  GFP_KERNEL);	if (hi == NULL) {		SBP2_ERR("out of memory in sbp2_add_host");		return;	}	/* Initialize some host stuff */	memset(hi, 0, sizeof(struct sbp2scsi_host_info));	INIT_LIST_HEAD(&hi->list);	INIT_LIST_HEAD(&hi->sbp2_req_inuse);	INIT_LIST_HEAD(&hi->sbp2_req_free);	hi->host = host;	hi->sbp2_command_lock = SPIN_LOCK_UNLOCKED;	hi->sbp2_request_packet_lock = SPIN_LOCK_UNLOCKED;	/* Create our request packet pool (pool of packets for use in I/O) */	if (sbp2util_create_request_packet_pool(hi)) {		SBP2_ERR("sbp2util_create_request_packet_pool failed!");		return;	}	sbp2_spin_lock(&sbp2_host_info_lock, flags);	list_add_tail(&hi->list, &sbp2_host_info_list);	sbp2_spin_unlock(&sbp2_host_info_lock, flags);	/* Register our host with the SCSI stack. */	hi->scsi_host = scsi_register (&scsi_driver_template, sizeof(void *));	if (hi->scsi_host) {		hi->scsi_host->hostdata[0] = (unsigned long)hi;		hi->scsi_host->max_id = SBP2SCSI_MAX_SCSI_IDS;	}	scsi_driver_template.present++;	return;}/* * This fuction returns a host info structure from the host structure, in * case we have multiple hosts. */static struct sbp2scsi_host_info *sbp2_find_host_info(struct hpsb_host *host){	struct list_head *lh;	struct sbp2scsi_host_info *hi;	list_for_each (lh, &sbp2_host_info_list) {		hi = list_entry(lh, struct sbp2scsi_host_info, list);		if (hi->host == host)			return hi;	}	return NULL;}/* * This function returns a host info structure for a given Scsi_Host * struct. */static struct sbp2scsi_host_info *sbp2_find_host_info_scsi(struct Scsi_Host *host){	struct list_head *lh;	struct sbp2scsi_host_info *hi;	list_for_each (lh, &sbp2_host_info_list) {		hi = list_entry(lh, struct sbp2scsi_host_info, list);		if (hi->scsi_host == host)			return hi;	}	return NULL;}/* * This function is called when a host is removed. */static void sbp2_remove_host(struct hpsb_host *host){	struct sbp2scsi_host_info *hi;	unsigned long flags;	SBP2_DEBUG("sbp2_remove_host");	sbp2_spin_lock(&sbp2_host_info_lock, flags);	hi = sbp2_find_host_info(host);	if (hi != NULL) {		sbp2util_remove_request_packet_pool(hi);		list_del(&hi->list);		kfree(hi);	}	else		SBP2_ERR("attempt to remove unknown host %p", host);	sbp2_spin_unlock(&sbp2_host_info_lock, flags);}/* * 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 sbp2scsi_host_info *hi, struct unit_directory *ud){	struct scsi_id_instance_data *scsi_id = NULL;	struct node_entry *ne;	int i;	SBP2_DEBUG("sbp2_start_device");	ne = ud->ne;	/*	 * This really is a "new" device plugged in. Let's allocate memory	 * for our scsi id instance data.	 */	scsi_id = (struct scsi_id_instance_data *)kmalloc(sizeof(struct scsi_id_instance_data),							  GFP_KERNEL);	if (!scsi_id)		goto alloc_fail_first;	memset(scsi_id, 0, sizeof(struct scsi_id_instance_data));	/* 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");	/* 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 == NULL) {alloc_fail:		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);alloc_fail_first:		SBP2_ERR ("Could not allocate memory for scsi_id");		return(-ENOMEM);	}	SBP2_DMA_ALLOC("consistent DMA region for login ORB");	/*	 * Initialize some of the fields in this structure	 */	scsi_id->ne = ne;	scsi_id->ud = ud;	scsi_id->speed_code = SPEED_100;	scsi_id->max_payload_size = sbp2_speedto_maxrec[SPEED_100];	ud->driver_data = scsi_id;	atomic_set(&scsi_id->sbp2_login_complete, 0);	/* 	 * Initialize structures needed for the command orb pool.	 */	INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse);	INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed);	scsi_id->sbp2_command_orb_lock = SPIN_LOCK_UNLOCKED;	scsi_id->sbp2_total_command_orbs = 0;	/*	 * Make sure that we've gotten ahold of the sbp2 management agent	 * address. Also figure out the command set being used (SCSI or	 * RBC).	 */	sbp2_parse_unit_directory(scsi_id);	scsi_id->sbp2_total_command_orbs = SBP2_MAX_COMMAND_ORBS;	/* 	 * Knock the total command orbs down if we are serializing I/O	 */	if (sbp2_serialize_io) {		scsi_id->sbp2_total_command_orbs = 2;	/* one extra for good measure */	}	/*	 * Find an empty spot to stick our scsi id instance data. 	 */	for (i = 0; i < SBP2SCSI_MAX_SCSI_IDS; 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, hi)) {		SBP2_ERR("sbp2util_create_command_orb_pool failed!");		sbp2_remove_device(hi, scsi_id);		return -ENOMEM;	}	/*	 * Make sure we are not out of space	 */	if (i == SBP2SCSI_MAX_SCSI_IDS) {		SBP2_ERR("No slots left for SBP-2 device");		sbp2_remove_device(hi, scsi_id);		return -EBUSY;	}	/*	 * Login to the sbp-2 device	 */	if (sbp2_login_device(hi, scsi_id)) {		/* Login failed, just remove the device. */		SBP2_ERR("sbp2_login_device failed");		sbp2_remove_device(hi, scsi_id);		return -EBUSY;	}	/*	 * Set max retries to something large on the device	 */	sbp2_set_busy_timeout(hi, scsi_id);		/*	 * 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);}#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, unsigned int length){        /*         * 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, unsigned int length){        /*         * 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 is called in order to login to a particular SBP-2 device, * after a bus reset. */

⌨️ 快捷键说明

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