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

📄 sbp2.c

📁 这是关于ieee1394的最新源码,上面包含了所有更新的部分!
💻 C
📖 第 1 页 / 共 5 页
字号:
	u64 addr;	int retval;	unsigned long flags;	SBP2_DEBUG_ENTER();	cancel_delayed_work(&scsi_id->protocol_work);	if (wait)		flush_scheduled_work();	data = ntohl(SBP2_AGENT_RESET_DATA);	addr = scsi_id->sbp2_command_block_agent_addr + SBP2_AGENT_RESET_OFFSET;	if (wait)		retval = hpsb_node_write(scsi_id->ne, addr, &data, 4);	else		retval = sbp2util_node_write_no_wait(scsi_id->ne, addr, &data, 4);	if (retval < 0) {		SBP2_ERR("hpsb_node_write failed.\n");		return -EIO;	}	/*	 * Need to make sure orb pointer is written on next command	 */	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);	scsi_id->last_orb = NULL;	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);	return 0;}static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,				     struct sbp2scsi_host_info *hi,				     struct sbp2_command_info *command,				     unsigned int scsi_use_sg,				     struct scatterlist *sgpnt,				     u32 orb_direction,				     enum dma_data_direction dma_dir){	command->dma_dir = dma_dir;	orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);	orb->misc |= ORB_SET_DIRECTION(orb_direction);	/* Special case if only one element (and less than 64KB in size) */	if ((scsi_use_sg == 1) &&	    (sgpnt[0].length <= SBP2_MAX_SG_ELEMENT_LENGTH)) {		SBP2_DEBUG("Only one s/g element");		command->dma_size = sgpnt[0].length;		command->dma_type = CMD_DMA_PAGE;		command->cmd_dma = pci_map_page(hi->host->pdev,						sgpnt[0].page,						sgpnt[0].offset,						command->dma_size,						command->dma_dir);		SBP2_DMA_ALLOC("single page scatter element");		orb->data_descriptor_lo = command->cmd_dma;		orb->misc |= ORB_SET_DATA_SIZE(command->dma_size);	} else {		struct sbp2_unrestricted_page_table *sg_element =					&command->scatter_gather_element[0];		u32 sg_count, sg_len;		dma_addr_t sg_addr;		int i, count = pci_map_sg(hi->host->pdev, sgpnt, scsi_use_sg,					  dma_dir);		SBP2_DMA_ALLOC("scatter list");		command->dma_size = scsi_use_sg;		command->sge_buffer = sgpnt;		/* use page tables (s/g) */		orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);		orb->data_descriptor_lo = command->sge_dma;		/*		 * Loop through and fill out our sbp-2 page tables		 * (and split up anything too large)		 */		for (i = 0, sg_count = 0 ; i < count; i++, sgpnt++) {			sg_len = sg_dma_len(sgpnt);			sg_addr = sg_dma_address(sgpnt);			while (sg_len) {				sg_element[sg_count].segment_base_lo = sg_addr;				if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {					sg_element[sg_count].length_segment_base_hi =						PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);					sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;					sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;				} else {					sg_element[sg_count].length_segment_base_hi =						PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);					sg_len = 0;				}				sg_count++;			}		}		/* Number of page table (s/g) elements */		orb->misc |= ORB_SET_DATA_SIZE(sg_count);		sbp2util_packet_dump(sg_element,				     (sizeof(struct sbp2_unrestricted_page_table)) * sg_count,				     "sbp2 s/g list", command->sge_dma);		/* Byte swap page tables if necessary */		sbp2util_cpu_to_be32_buffer(sg_element,					    (sizeof(struct sbp2_unrestricted_page_table)) *					    sg_count);	}}static void sbp2_prep_command_orb_no_sg(struct sbp2_command_orb *orb,					struct sbp2scsi_host_info *hi,					struct sbp2_command_info *command,					struct scatterlist *sgpnt,					u32 orb_direction,					unsigned int scsi_request_bufflen,					void *scsi_request_buffer,					enum dma_data_direction dma_dir){	command->dma_dir = dma_dir;	command->dma_size = scsi_request_bufflen;	command->dma_type = CMD_DMA_SINGLE;	command->cmd_dma = pci_map_single(hi->host->pdev, scsi_request_buffer,					  command->dma_size, command->dma_dir);	orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);	orb->misc |= ORB_SET_DIRECTION(orb_direction);	SBP2_DMA_ALLOC("single bulk");	/*	 * Handle case where we get a command w/o s/g enabled (but	 * check for transfers larger than 64K)	 */	if (scsi_request_bufflen <= SBP2_MAX_SG_ELEMENT_LENGTH) {		orb->data_descriptor_lo = command->cmd_dma;		orb->misc |= ORB_SET_DATA_SIZE(scsi_request_bufflen);	} else {		struct sbp2_unrestricted_page_table *sg_element =			&command->scatter_gather_element[0];		u32 sg_count, sg_len;		dma_addr_t sg_addr;		/*		 * Need to turn this into page tables, since the		 * buffer is too large.		 */		orb->data_descriptor_lo = command->sge_dma;		/* Use page tables (s/g) */		orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);		/*		 * fill out our sbp-2 page tables (and split up		 * the large buffer)		 */		sg_count = 0;		sg_len = scsi_request_bufflen;		sg_addr = command->cmd_dma;		while (sg_len) {			sg_element[sg_count].segment_base_lo = sg_addr;			if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {				sg_element[sg_count].length_segment_base_hi =					PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);				sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;				sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;			} else {				sg_element[sg_count].length_segment_base_hi =					PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);				sg_len = 0;			}			sg_count++;		}		/* Number of page table (s/g) elements */		orb->misc |= ORB_SET_DATA_SIZE(sg_count);		sbp2util_packet_dump(sg_element,				     (sizeof(struct sbp2_unrestricted_page_table)) * sg_count,				     "sbp2 s/g list", command->sge_dma);		/* Byte swap page tables if necessary */		sbp2util_cpu_to_be32_buffer(sg_element,					    (sizeof(struct sbp2_unrestricted_page_table)) *					     sg_count);	}}/* * This function is called to create the actual command orb and s/g list * out of the scsi command itself. */static void sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,				    struct sbp2_command_info *command,				    unchar *scsi_cmd,				    unsigned int scsi_use_sg,				    unsigned int scsi_request_bufflen,				    void *scsi_request_buffer,				    enum dma_data_direction dma_dir){	struct sbp2scsi_host_info *hi = scsi_id->hi;	struct scatterlist *sgpnt = (struct scatterlist *)scsi_request_buffer;	struct sbp2_command_orb *command_orb = &command->command_orb;	u32 orb_direction;	/*	 * Set-up our command ORB..	 *	 * NOTE: We're doing unrestricted page tables (s/g), as this is	 * best performance (at least with the devices I have). This means	 * that data_size becomes the number of s/g elements, and	 * page_size should be zero (for unrestricted).	 */	command_orb->next_ORB_hi = ORB_SET_NULL_PTR(1);	command_orb->next_ORB_lo = 0x0;	command_orb->misc = ORB_SET_MAX_PAYLOAD(scsi_id->max_payload_size);	command_orb->misc |= ORB_SET_SPEED(scsi_id->speed_code);	command_orb->misc |= ORB_SET_NOTIFY(1);	/* Notify us when complete */	if (dma_dir == DMA_NONE)		orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER;	else if (dma_dir == DMA_TO_DEVICE && scsi_request_bufflen)		orb_direction = ORB_DIRECTION_WRITE_TO_MEDIA;	else if (dma_dir == DMA_FROM_DEVICE && scsi_request_bufflen)		orb_direction = ORB_DIRECTION_READ_FROM_MEDIA;	else {		SBP2_WARN("Falling back to DMA_NONE");		orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER;	}	/* Set-up our pagetable stuff */	if (orb_direction == ORB_DIRECTION_NO_DATA_TRANSFER) {		SBP2_DEBUG("No data transfer");		command_orb->data_descriptor_hi = 0x0;		command_orb->data_descriptor_lo = 0x0;		command_orb->misc |= ORB_SET_DIRECTION(1);	} else if (scsi_use_sg) {		SBP2_DEBUG("Use scatter/gather");		sbp2_prep_command_orb_sg(command_orb, hi, command, scsi_use_sg,					 sgpnt, orb_direction, dma_dir);	} else {		SBP2_DEBUG("No scatter/gather");		sbp2_prep_command_orb_no_sg(command_orb, hi, command, sgpnt,					    orb_direction, scsi_request_bufflen,					    scsi_request_buffer, dma_dir);	}	/* Byte swap command ORB if necessary */	sbp2util_cpu_to_be32_buffer(command_orb, sizeof(struct sbp2_command_orb));	/* Put our scsi command in the command ORB */	memset(command_orb->cdb, 0, 12);	memcpy(command_orb->cdb, scsi_cmd, COMMAND_SIZE(*scsi_cmd));}/* * This function is called in order to begin a regular SBP-2 command. */static void sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,				 struct sbp2_command_info *command){	struct sbp2scsi_host_info *hi = scsi_id->hi;	struct sbp2_command_orb *command_orb = &command->command_orb;	struct sbp2_command_orb *last_orb;	dma_addr_t last_orb_dma;	u64 addr = scsi_id->sbp2_command_block_agent_addr;	quadlet_t data[2];	size_t length;	unsigned long flags;	outstanding_orb_incr;	SBP2_ORB_DEBUG("sending command orb %p, total orbs = %x",		       command_orb, global_outstanding_command_orbs);	pci_dma_sync_single_for_device(hi->host->pdev, command->command_orb_dma,				       sizeof(struct sbp2_command_orb),				       PCI_DMA_TODEVICE);	pci_dma_sync_single_for_device(hi->host->pdev, command->sge_dma,				       sizeof(command->scatter_gather_element),				       PCI_DMA_BIDIRECTIONAL);	/*	 * Check to see if there are any previous orbs to use	 */	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);	last_orb = scsi_id->last_orb;	last_orb_dma = scsi_id->last_orb_dma;	if (!last_orb) {		/*		 * last_orb == NULL means: We know that the target's fetch agent		 * is not active right now.		 */		addr += SBP2_ORB_POINTER_OFFSET;		data[0] = ORB_SET_NODE_ID(hi->host->node_id);		data[1] = command->command_orb_dma;		sbp2util_cpu_to_be32_buffer(data, 8);		length = 8;	} else {		/*		 * last_orb != NULL means: We know that the target's fetch agent		 * is (very probably) not dead or in reset state right now.		 * We have an ORB already sent that we can append a new one to.		 * The target's fetch agent may or may not have read this		 * previous ORB yet.		 */		pci_dma_sync_single_for_cpu(hi->host->pdev, last_orb_dma,					    sizeof(struct sbp2_command_orb),					    PCI_DMA_TODEVICE);		last_orb->next_ORB_lo = cpu_to_be32(command->command_orb_dma);		wmb();		/* Tells hardware that this pointer is valid */		last_orb->next_ORB_hi = 0;		pci_dma_sync_single_for_device(hi->host->pdev, last_orb_dma,					       sizeof(struct sbp2_command_orb),					       PCI_DMA_TODEVICE);		addr += SBP2_DOORBELL_OFFSET;		data[0] = 0;		length = 4;	}	scsi_id->last_orb = command_orb;	scsi_id->last_orb_dma = command->command_orb_dma;	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);	SBP2_ORB_DEBUG("write to %s register, command orb %p",			last_orb ? "DOORBELL" : "ORB_POINTER", command_orb);	if (sbp2util_node_write_no_wait(scsi_id->ne, addr, data, length)) {		/*		 * sbp2util_node_write_no_wait failed. We certainly ran out		 * of transaction labels, perhaps just because there were no		 * context switches which gave khpsbpkt a chance to collect		 * free tlabels. Try again in non-atomic context. If necessary,		 * the workqueue job will sleep to guaranteedly get a tlabel.		 * We do not accept new commands until the job is over.		 */		scsi_block_requests(scsi_id->scsi_host);		PREPARE_WORK(&scsi_id->protocol_work,			     last_orb ? sbp2util_write_doorbell:					sbp2util_write_orb_pointer,			     scsi_id);		schedule_work(&scsi_id->protocol_work);	}}/* * This function is called in order to begin a regular SBP-2 command. */static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,			     struct scsi_cmnd *SCpnt,			     void (*done)(struct scsi_cmnd *)){	unchar *cmd = (unchar *) SCpnt->cmnd;	unsigned int request_bufflen = SCpnt->request_bufflen;	struct sbp2_command_info *command;	SBP2_DEBUG_ENTER();	SBP2_DEBUG("SCSI transfer size = %x", request_bufflen);	SBP2_DEBUG("SCSI s/g elements = %x", (unsigned int)SCpnt->use_sg);	/*	 * Allocate a command orb and s/g structure	 */	command = sbp2util_allocate_command_orb(scsi_id, SCpnt, done);	if (!command) {		return -EIO;	}	/*	 * Now actually fill in the comamnd orb and sbp2 s/g list	 */	sbp2_create_command_orb(scsi_id, command, cmd, SCpnt->use_sg,				request_bufflen, SCpnt->request_buffer,				SCpnt->sc_data_direction);	sbp2util_packet_dump(&command->command_orb, sizeof(struct sbp2_command_orb),			     "sbp2 command orb", command->command_orb_dma);	/*	 * Link up the orb, and ring the doorbell if needed	 */	sbp2_link_orb_command(scsi_id, command);	return 0;}/* * Translates SBP-2 status into SCSI sense data for check conditions */static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data){	SBP2_DEBUG_ENTER();	/*	 * Ok, it's pretty ugly...   ;-)	 */	sense_data[0] = 0x70;	sense_data[1] = 0x0;	sense_data[2] = sbp2_status[9];	sense_data[3] = sbp2_status[12];	sense_data[4] = sbp2_status[13];	sense_data[5] = sbp2_status[14];	sense_data[6] = sbp2_status[15];	sense_data[7] = 10;	sense_data[8] = sbp2_status[16];	sense_data[9] = sbp2_status[17];	sense_data[10] = sbp2_status[18];	sense_data[11] = sbp2_status[19];	sense_data[12] = sbp2_status[10];	sense_data[13] = sbp2_status[11];	sense_data[14] = sbp2_status[20];	sense_data[15] = sbp2_status[21];	return sbp2_status[8] & 0x3f;	/* return scsi status */}/* * This function deals with status writes from the SBP-2 device */static int sbp2_handle

⌨️ 快捷键说明

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