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

📄 sbp2.c

📁 这个是uClinux下的ieee1394驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
		packet->data_size = data_size;		INIT_LIST_HEAD(&packet->list);		sema_init(&packet->state_change, 0);		packet->state = hpsb_unused;		packet->data_be = 1;				hpsb_node_fill_packet(ne, packet);		packet->tlabel = get_tlabel(hi->host, packet->node_id, 0);		if (!data_size) {			fill_async_writequad(packet, addr, data);		} else {			fill_async_writeblock(packet, addr, data_size);         		}		/*		 * Set up a task queue completion routine, which returns		 * the packet to the free list and releases the tlabel.		 */		request_packet->tq.routine = (void (*)(void*))sbp2util_free_request_packet;		request_packet->tq.data = request_packet;		request_packet->hi_context = hi;		hpsb_add_packet_complete_task(packet, &request_packet->tq);		/*		 * Now, put the packet on the in-use list.		 */		list_add_tail(&request_packet->list, &hi->sbp2_req_inuse);	} else {		SBP2_ERR("sbp2util_allocate_request_packet - no packets available!");	}	sbp2_spin_unlock(&hi->sbp2_request_packet_lock, flags);	return(request_packet);}/* * This function is called to return a packet to our packet pool. It is * also called as a completion routine when a request packet is completed. */static void sbp2util_free_request_packet(struct sbp2_request_packet *request_packet){	unsigned long flags;	struct sbp2scsi_host_info *hi = request_packet->hi_context;	/*	 * Free the tlabel, and return the packet to the free pool.	 */	sbp2_spin_lock(&hi->sbp2_request_packet_lock, flags);	free_tlabel(hi->host, LOCAL_BUS | request_packet->packet->node_id,		    request_packet->packet->tlabel);	list_del(&request_packet->list);	list_add_tail(&request_packet->list, &hi->sbp2_req_free);	sbp2_spin_unlock(&hi->sbp2_request_packet_lock, flags);	return;}/* * This function is called to create a pool of command orbs used for * command processing. It is called when a new sbp2 device is detected. */static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_id,					    struct sbp2scsi_host_info *hi){	int i;	unsigned long flags;	struct sbp2_command_info *command;        	sbp2_spin_lock(&scsi_id->sbp2_command_orb_lock, flags);	for (i = 0; i < scsi_id->sbp2_total_command_orbs; i++) {		command = (struct sbp2_command_info *)		    kmalloc(sizeof(struct sbp2_command_info), GFP_KERNEL);		if (!command) {			sbp2_spin_unlock(&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);	}	sbp2_spin_unlock(&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 sbp2scsi_host_info *hi){	struct list_head *lh, *next;	struct sbp2_command_info *command;	unsigned long flags;        	sbp2_spin_lock(&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(hi->host->pdev, command->command_orb_dma,					 sizeof(struct sbp2_command_orb),					 PCI_DMA_BIDIRECTIONAL);			SBP2_DMA_FREE("single command orb DMA");			pci_unmap_single(hi->host->pdev, command->sge_dma,					 sizeof(command->scatter_gather_element),					 PCI_DMA_BIDIRECTIONAL);			SBP2_DMA_FREE("scatter_gather_element");			kfree(command);		}	}	sbp2_spin_unlock(&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;	sbp2_spin_lock(&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) {				sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags);				return (command);			}		}	}	sbp2_spin_unlock(&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;	sbp2_spin_lock(&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) {				sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags);				return (command);			}		}	}	sbp2_spin_unlock(&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 sbp2scsi_host_info *hi){	struct list_head *lh;	struct sbp2_command_info *command = NULL;	unsigned long flags;	sbp2_spin_lock(&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!");	}	sbp2_spin_unlock(&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 sbp2scsi_host_info *hi;		hi = (struct sbp2scsi_host_info *) command->Current_SCpnt->host->hostdata[0];	if (hi == NULL) {		printk(KERN_ERR "%s: hi == NULL\n", __FUNCTION__);		return;	}	if (command->cmd_dma) {		if (command->dma_type == CMD_DMA_SINGLE) {			pci_unmap_single(hi->host->pdev, command->cmd_dma,					 command->dma_size, command->dma_dir);			SBP2_DMA_FREE("single bulk");		} else if (command->dma_type == CMD_DMA_PAGE) {#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,13)			pci_unmap_single(hi->host->pdev, command->cmd_dma,					 command->dma_size, command->dma_dir);#else			pci_unmap_page(hi->host->pdev, command->cmd_dma,				       command->dma_size, command->dma_dir);#endif /* Linux version < 2.4.13 */			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(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 + 				SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(SBP2SCSI_MAX_SCSI_IDS+1));	/*	 * Handle data movement if physical dma is not enabled/supported on host controller	 */#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA	hpsb_register_addrspace(sbp2_hl_handle, &sbp2_physdma_ops, 0x0ULL, 0xfffffffcULL);#endif	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.

⌨️ 快捷键说明

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