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

📄 sbp2.c

📁 IEE1394 火线接口驱动 for linux
💻 C
📖 第 1 页 / 共 5 页
字号:
	for (i = 0; i < orbs; i++) {		command = (struct sbp2_command_info *)		    kmalloc(sizeof(struct sbp2_command_info), GFP_ATOMIC);		if (!command) {			spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);			return(-ENOMEM);		}		memset(command, '\0', sizeof(struct sbp2_command_info));		command->command_orb_dma =			pci_map_single (hi->host->pdev, &command->command_orb,					sizeof(struct sbp2_command_orb),					PCI_DMA_BIDIRECTIONAL);		SBP2_DMA_ALLOC("single command orb DMA");		command->sge_dma =			pci_map_single (hi->host->pdev, &command->scatter_gather_element,					sizeof(command->scatter_gather_element),					PCI_DMA_BIDIRECTIONAL);		SBP2_DMA_ALLOC("scatter_gather_element");		INIT_LIST_HEAD(&command->list);		list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed);	}	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);	return 0;}/* * This function is called to delete a pool of command orbs. */static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_id){	struct hpsb_host *host = scsi_id->hi->host;	struct list_head *lh, *next;	struct sbp2_command_info *command;	unsigned long flags;        	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);	if (!list_empty(&scsi_id->sbp2_command_orb_completed)) {		list_for_each_safe(lh, next, &scsi_id->sbp2_command_orb_completed) {			command = list_entry(lh, struct sbp2_command_info, list);			/* Release our generic DMA's */			pci_unmap_single(host->pdev, command->command_orb_dma,					 sizeof(struct sbp2_command_orb),					 PCI_DMA_BIDIRECTIONAL);			SBP2_DMA_FREE("single command orb DMA");			pci_unmap_single(host->pdev, command->sge_dma,					 sizeof(command->scatter_gather_element),					 PCI_DMA_BIDIRECTIONAL);			SBP2_DMA_FREE("scatter_gather_element");			kfree(command);		}	}	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);	return;}/*  * This function finds the sbp2_command for a given outstanding command * orb.Only looks at the inuse list. */static struct sbp2_command_info *sbp2util_find_command_for_orb(		struct scsi_id_instance_data *scsi_id, dma_addr_t orb){	struct list_head *lh;	struct sbp2_command_info *command;	unsigned long flags;	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);	if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {		list_for_each(lh, &scsi_id->sbp2_command_orb_inuse) {			command = list_entry(lh, struct sbp2_command_info, list);			if (command->command_orb_dma == orb) {				spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);				return (command);			}		}	}	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);	SBP2_ORB_DEBUG("could not match command orb %x", (unsigned int)orb);	return(NULL);}/*  * This function finds the sbp2_command for a given outstanding SCpnt. * Only looks at the inuse list. */static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_instance_data *scsi_id, void *SCpnt){	struct list_head *lh;	struct sbp2_command_info *command;	unsigned long flags;	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);	if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) {		list_for_each(lh, &scsi_id->sbp2_command_orb_inuse) {			command = list_entry(lh, struct sbp2_command_info, list);			if (command->Current_SCpnt == SCpnt) {				spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);				return (command);			}		}	}	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);	return(NULL);}/* * This function allocates a command orb used to send a scsi command. */static struct sbp2_command_info *sbp2util_allocate_command_orb(		struct scsi_id_instance_data *scsi_id, 		Scsi_Cmnd *Current_SCpnt, 		void (*Current_done)(Scsi_Cmnd *)){	struct list_head *lh;	struct sbp2_command_info *command = NULL;	unsigned long flags;	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);	if (!list_empty(&scsi_id->sbp2_command_orb_completed)) {		lh = scsi_id->sbp2_command_orb_completed.next;		list_del(lh);		command = list_entry(lh, struct sbp2_command_info, list);		command->Current_done = Current_done;		command->Current_SCpnt = Current_SCpnt;		list_add_tail(&command->list, &scsi_id->sbp2_command_orb_inuse);	} else {		SBP2_ERR("sbp2util_allocate_command_orb - No orbs available!");	}	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);	return (command);}/* Free our DMA's */static void sbp2util_free_command_dma(struct sbp2_command_info *command){	struct hpsb_host *host;	host = hpsb_get_host_bykey(&sbp2_highlevel,		(unsigned long)command->Current_SCpnt->device->host->hostt);	if (!host) {		printk(KERN_ERR "%s: host == NULL\n", __FUNCTION__);		return;	}	if (command->cmd_dma) {		if (command->dma_type == CMD_DMA_SINGLE) {			pci_unmap_single(host->pdev, command->cmd_dma,					 command->dma_size, command->dma_dir);			SBP2_DMA_FREE("single bulk");		} else if (command->dma_type == CMD_DMA_PAGE) {			pci_unmap_page(host->pdev, command->cmd_dma,				       command->dma_size, command->dma_dir);			SBP2_DMA_FREE("single page");		} /* XXX: Check for CMD_DMA_NONE bug */		command->dma_type = CMD_DMA_NONE;		command->cmd_dma = 0;	}	if (command->sge_buffer) {		pci_unmap_sg(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;	spin_lock_irqsave(&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);	spin_unlock_irqrestore(&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. */static int sbp2scsi_detect(Scsi_Host_Template *tpnt){	struct Scsi_Host *scsi_host;	struct hpsb_host *host = hpsb_get_host_bykey(&sbp2_highlevel, (unsigned long)tpnt);	SBP2_DEBUG("sbp2scsi_detect");	/* Register our host with the SCSI stack. */	if (!(scsi_host = scsi_register(tpnt, 0)))		return 0;	scsi_set_pci_device(scsi_host, host->pdev);	tpnt->present = 1;	return tpnt->present;}static int sbp2_probe(struct unit_directory *ud){	struct sbp2scsi_host_info *hi;	SBP2_DEBUG(__FUNCTION__);	/* Don't probe UD's that have the LUN flag. We'll probe the LUN(s)	 * instead. */	if (ud->flags & UNIT_DIRECTORY_HAS_LUN_DIRECTORY)		return -1;	/* This will only add it if it doesn't exist */	hi = sbp2_add_host(ud->ne->host);	if (!hi)		return -1;	return sbp2_start_ud(hi, ud);}static void sbp2_disconnect(struct unit_directory *ud){	struct scsi_id_group *scsi_group = ud->driver_data;	struct list_head *lh, *next;	struct scsi_id_instance_data *scsi_id;	SBP2_DEBUG("sbp2_disconnect");	list_for_each_safe (lh, next, &scsi_group->scsi_id_list) {		scsi_id = list_entry(lh, struct scsi_id_instance_data, list);		if (scsi_id) {			sbp2_logout_device(scsi_id); 			sbp2_remove_device(scsi_id);		}	}	kfree(scsi_group);}static void sbp2_update(struct unit_directory *ud){	struct sbp2scsi_host_info *hi;	struct scsi_id_group *scsi_group = ud->driver_data;	struct list_head *lh, *next;	struct scsi_id_instance_data *scsi_id;	unsigned long flags;	SBP2_DEBUG("sbp2_update");	hi = hpsb_get_hostinfo(&sbp2_highlevel, ud->ne->host);	list_for_each_safe (lh, next, &scsi_group->scsi_id_list) {		scsi_id = list_entry(lh, struct scsi_id_instance_data, list);		if (sbp2_reconnect_device(scsi_id)) {			/* 			 * Ok, reconnect has failed. Perhaps we didn't			 * reconnect fast enough. Try doing a regular login.			 */			if (sbp2_login_device(scsi_id)) {				/* Login failed too, just remove the device. */				SBP2_ERR("sbp2_reconnect_device failed!");				sbp2_remove_device(scsi_id);				continue;			}		}		/* 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, 0);			/* Get the max speed and packet size that we can use. */		sbp2_max_speed_and_size(scsi_id);		/* Complete any pending commands with busy (so they get		 * retried) and remove them from our queue		 */		spin_lock_irqsave(&hi->sbp2_command_lock, flags);		sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY);		spin_unlock_irqrestore(&hi->sbp2_command_lock, flags);	}	if (list_empty(&scsi_group->scsi_id_list)) {		hpsb_release_unit_directory(ud);		kfree(scsi_group);	}}/* * We go ahead and allocate some memory for our host info structure, and * init some structures. */static struct sbp2scsi_host_info *sbp2_add_host(struct hpsb_host *host){	struct sbp2scsi_host_info *hi;	SBP2_DEBUG("sbp2_add_host");	/* Check for existing hostinfo */	hi = hpsb_get_hostinfo(&sbp2_highlevel, host);	if (hi)		return hi;	/* Allocate some memory for our host info structure */	hi = hpsb_create_hostinfo(&sbp2_highlevel, host, sizeof(*hi));	if (hi == NULL) {		SBP2_ERR("out of memory in sbp2_add_host");		return NULL;	}	/* Initialize some host stuff */	hi->host = host;	hi->sbp2_command_lock = SPIN_LOCK_UNLOCKED;	memcpy(&hi->sht, &scsi_driver_template, sizeof hi->sht);	sprintf(hi->proc_name, "%s_%d", SBP2_DEVICE_NAME, host->id);	hi->sht.proc_name = hi->proc_name;	hpsb_set_hostinfo_key(&sbp2_highlevel, host, (unsigned long)&hi->sht);	if (SCSI_REGISTER_HOST(&hi->sht)) {                SBP2_ERR("Failed to register scsi template for ieee1394 host");		hpsb_destroy_hostinfo(&sbp2_highlevel, host);                return NULL;        }	for (hi->scsi_host = scsi_hostlist; hi->scsi_host; hi->scsi_host = hi->scsi_host->next)		if (hi->scsi_host->hostt == &hi->sht)			break;	if (!hi->scsi_host) {		SBP2_ERR("Failed to register scsi host for ieee1394 host");		SCSI_UNREGISTER_HOST(&hi->sht);		hpsb_destroy_hostinfo(&sbp2_highlevel, host);		return NULL;	}	hi->scsi_host->max_id = SBP2SCSI_MAX_SCSI_IDS;	return hi;}/* * This function is called when a host is removed. */static void sbp2_remove_host(struct hpsb_host *host){	struct sbp2scsi_host_info *hi;	SBP2_DEBUG("sbp2_remove_host");	hi = hpsb_get_hostinfo(&sbp2_highlevel, host);	if (hi)		SCSI_UNREGISTER_HOST(&hi->sht);}static int sbp2_start_ud(struct sbp2scsi_host_info *hi, struct unit_directory *ud){	struct scsi_id_instance_data *scsi_id;	struct scsi_id_group *scsi_group;	struct list_head *lh, *next;	SBP2_DEBUG("sbp2_start_ud");	scsi_group = kmalloc(sizeof(*scsi_group), GFP_KERNEL);	if (!scsi_group) {		SBP2_ERR ("Could not allocate memory for scsi_group");		return -ENOMEM;	}	INIT_LIST_HEAD(&scsi_group->scsi_id_list);	ud->driver_data = scsi_group;	sbp2_parse_unit_directory(scsi_group, ud);	list_for_each_safe (lh, next, &scsi_group->scsi_id_list) {		scsi_id = list_entry(lh, struct scsi_id_instance_data, list);		scsi_id->ne = ud->ne;		scsi_id->hi = hi;		scsi_id->speed_code = IEEE1394_SPEED_100;		scsi_id->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100];		atomic_set(&scsi_id->sbp2_login_complete, 0);		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;		sbp2_start_device(scsi_id);	}	/* Check to see if any of our devices survived the ordeal */	if (list_empty(&scsi_group->scsi_id_list)) {		kfree(scsi_group);		return -ENODEV;	}	return 0;}/* * 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 i;	SBP2_DEBUG("sbp2_start_device");

⌨️ 快捷键说明

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