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

📄 sbp2.c

📁 Armlinux ieee1394接口驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (command->sge_buffer) {		pci_unmap_sg(hi->host->pdev, command->sge_buffer,			     command->dma_size, command->dma_dir);		SBP2_DMA_FREE("scatter list");		command->sge_buffer = NULL;	}}/* * This function moves a command to the completed orb list. */static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id, struct sbp2_command_info *command){	unsigned long flags;	sbp2_spin_lock(&scsi_id->sbp2_command_orb_lock, flags);	list_del(&command->list);	sbp2util_free_command_dma(command);	list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed);	sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags);}/********************************************* * IEEE-1394 core driver stack related section *********************************************//* * This function is called at SCSI init in order to register our driver * with the IEEE-1394 stack. */int sbp2_init(void){	SBP2_DEBUG("sbp2_init");	/*	 * Register our high level driver with 1394 stack	 */	sbp2_hl_handle = hpsb_register_highlevel(SBP2_DEVICE_NAME, &sbp2_hl_ops);	if (sbp2_hl_handle == NULL) {		SBP2_ERR("sbp2 failed to register with ieee1394 highlevel");		return(-ENOMEM);	}	/*	 * Register our sbp2 status address space...	 */	hpsb_register_addrspace(sbp2_hl_handle, &sbp2_ops, SBP2_STATUS_FIFO_ADDRESS,				SBP2_STATUS_FIFO_ADDRESS + sizeof(struct sbp2_status_block));	hpsb_register_protocol(&sbp2_driver);	return 0;}/* * This function is called from cleanup module, or during shut-down, in * order to unregister our driver. */void sbp2_cleanup(void){	SBP2_DEBUG("sbp2_cleanup");	hpsb_unregister_protocol(&sbp2_driver);	if (sbp2_hl_handle) {		hpsb_unregister_highlevel(sbp2_hl_handle);		sbp2_hl_handle = NULL;	}}static int sbp2_probe(struct unit_directory *ud){	struct sbp2scsi_host_info *hi;	SBP2_DEBUG("sbp2_probe");	hi = sbp2_find_host_info(ud->ne->host);	return sbp2_start_device(hi, ud);}static void sbp2_disconnect(struct unit_directory *ud){	struct sbp2scsi_host_info *hi;	struct scsi_id_instance_data *scsi_id = ud->driver_data;	SBP2_DEBUG("sbp2_disconnect");	hi = sbp2_find_host_info(ud->ne->host);	if (hi != NULL) {		sbp2_logout_device(hi, scsi_id); 		sbp2_remove_device(hi, scsi_id);	}}static void sbp2_update(struct unit_directory *ud){	struct sbp2scsi_host_info *hi;	struct scsi_id_instance_data *scsi_id = ud->driver_data;	unsigned long flags;	SBP2_DEBUG("sbp2_update");	hi = sbp2_find_host_info(ud->ne->host);	if (sbp2_reconnect_device(hi, scsi_id)) {				/* Ok, reconnect has failed.  Perhaps we didn't		 * reconnect fast enough. Try doing a regular login.		 */		if (sbp2_login_device(hi, scsi_id)) {			/* Login failed too, just remove the device. */			SBP2_ERR("sbp2_reconnect_device failed!");			sbp2_remove_device(hi, scsi_id);			hpsb_release_unit_directory(ud);			return;		}	}	/* 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);	/* Complete any pending commands with busy (so they get	 * retried) and remove them from our queue	 */	sbp2_spin_lock(&hi->sbp2_command_lock, flags);	sbp2scsi_complete_all_commands(hi, scsi_id, DID_BUS_BUSY);	sbp2_spin_unlock(&hi->sbp2_command_lock, flags);}/* * This function is called after registering our operations in sbp2_init. * We go ahead and allocate some memory for our host info structure, and * init some structures. */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_host_count++;	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;	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 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);		sbp2_host_count--;		list_del(&hi->list);		scsi_unregister(hi->scsi_host);		scsi_driver_template.present--;		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;	init_waitqueue_head(&scsi_id->sbp2_login_wait);	/* 	 * 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 (serialize_io) {		scsi_id->sbp2_total_command_orbs = 2;	/* one extra for good measure */	}	/*	 * Allocate some extra command orb structures for devices with	 * 128KB limit.	 */	if (scsi_id->sbp2_firmware_revision == SBP2_128KB_BROKEN_FIRMWARE) {		scsi_id->sbp2_total_command_orbs *= 4;	} 	/*	 * 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);	

⌨️ 快捷键说明

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