qla_ip.c

来自「这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自」· C语言 代码 · 共 1,757 行 · 第 1/4 页

C
1,757
字号
		/* Therefore, only check mb0 for now */		if (/* mbxentry->status == CS_COMPLETE && */			mbxentry->mb0 == MBS_COMMAND_COMPLETE) {			/* Login successful */			ipdev->flags |= IP_DEV_FLAG_PRESENT;		}		else if (mbxentry->mb0 == MBS_PORT_ID_IN_USE) {			/* Different loop ID already assigned to port ID */			/* Use the one that is already assigned */			qla2x00_free_loopid(ha, ipdev->loop_id);			ipdev->loop_id = mbxentry->mb1;			/* Do logout first and then relogin */			qla2x00_ip_send_logout_port_iocb(ha, ipdev, 1);			qla2x00_ip_send_login_port_iocb(ha, ipdev, 1);		}		else if (mbxentry->mb0 == MBS_LOOP_ID_IN_USE) {			/* Loop ID already used for different port ID */			/* Get a new loop ID and reissue login request */			status = qla2x00_reserve_loopid(ha, &ipdev->loop_id);			if (status == QL_STATUS_SUCCESS) {				qla2x00_ip_send_login_port_iocb(ha, ipdev, 1);			}			else {				DEBUG12(printk("%s: out of loop IDs\n",						__func__);)				qla2x00_free_ip_block(ha, ipdev);			}		}		else {			/* Login failed, return resources */			DEBUG12(printk("%s: fabric login failed\n", __func__);)			qla2x00_free_loopid(ha, ipdev->loop_id);			qla2x00_free_ip_block(ha, ipdev);		}	}}/** * qla2x00_ip_inquiry() - Discover IP-capable adapters. * @adapter_num: adapter number to check (instance) * @inq_data: return bd_inquiry data of the discovered adapter * * This routine is called by the IP driver to discover adapters that support IP * and to get adapter parameters from the SCSI driver. * * Returns TRUE if the specified adapter supports IP. */#if defined (ISP2200)intqla2200_ip_inquiry(uint16_t adapter_num, struct bd_inquiry *inq_data)#elif defined(ISP2300)intqla2300_ip_inquiry(uint16_t adapter_num, struct bd_inquiry *inq_data)#endif{	scsi_qla_host_t	*ha;	/* Verify structure size and version */	if ((inq_data->length != BDI_LENGTH) ||		(inq_data->version != BDI_VERSION)) {		DEBUG12(printk("%s: incompatable structure\n", __func__);)		return (FALSE);	}	/* Find the specified host adapter */	for (ha = qla2x00_hostlist;		ha && ha->instance != adapter_num;		ha = ha->next);	if (ha) {		if (!ha->flags.online)			return (FALSE);		DEBUG12(printk("%s: found adapter %d\n",				__func__,				adapter_num);)		/* Return inquiry data to backdoor IP driver */		set_bit(BDI_IP_SUPPORT, &inq_data->options);		if (ha->flags.enable_64bit_addressing)			set_bit(BDI_64BIT_ADDRESSING, &inq_data->options);		inq_data->ha = ha;                		inq_data->risc_rec_q = ha->risc_rec_q;		inq_data->risc_rec_q_size = IP_BUFFER_QUEUE_DEPTH;		inq_data->link_speed = ha->current_speed;		memcpy(inq_data->port_name, ha->ip_port_name, WWN_SIZE);		inq_data->pdev = ha->pdev;		inq_data->ip_enable_routine = qla2x00_ip_enable;		inq_data->ip_disable_routine = qla2x00_ip_disable;		inq_data->ip_add_buffers_routine = qla2x00_add_buffers;		inq_data->ip_send_packet_routine = qla2x00_send_packet;		inq_data->ip_tx_timeout_routine = qla2x00_tx_timeout;		return (TRUE);	}	return (FALSE);}/** * qla2x00_ip_enable() - Create IP-driver/SCSI-driver IP connection. * @ha: SCSI driver HA context * @enable_data: bd_enable data describing the IP connection * * This routine is called by the IP driver to enable an IP connection to the * SCSI driver and to pass in IP driver parameters. * * The HA context is propagated with the specified @enable_data and the * Firmware is initialized for IP support. *  * Returns TRUE if the IP connection was successfully enabled. */static intqla2x00_ip_enable(scsi_qla_host_t *ha, struct bd_enable *enable_data){	int status;	DEBUG12(printk("%s: enable adapter %d\n", __func__, (int)ha->host_no);)	status = FALSE;	/* Verify structure size and version and adapter online */	if (!(ha->flags.online) ||		(enable_data->length != BDE_LENGTH) ||		(enable_data->version != BDE_VERSION)) {		DEBUG12(printk("%s: incompatable structure or offline\n",				__func__);)		return (status);	}	/* Save parameters from IP driver */	ha->mtu = enable_data->mtu;	ha->header_size = enable_data->header_size;	ha->receive_buffers = enable_data->receive_buffers;	ha->max_receive_buffers = enable_data->max_receive_buffers;	ha->receive_buff_data_size = enable_data->receive_buff_data_size;	if (test_bit(BDE_NOTIFY_ROUTINE, &enable_data->options)) {		ha->notify_routine = enable_data->notify_routine;		ha->notify_context = enable_data->notify_context;	}	ha->send_completion_routine = enable_data->send_completion_routine;	ha->receive_packets_routine = enable_data->receive_packets_routine;	ha->receive_packets_context = enable_data->receive_packets_context;	/* Enable RISC IP support */	status = qla2x00_ip_initialize(ha);	if (!status) {		DEBUG12(printk("%s: IP initialization failed", __func__);)		ha->notify_routine = NULL;	}	return (status);}/** * qla2x00_ip_disable() - Remove IP-driver/SCSI-driver IP connection. * @ha: SCSI driver HA context * * This routine is called by the IP driver to disable a previously created IP * connection. * * A Firmware call to disable IP support is issued. */static voidqla2x00_ip_disable(scsi_qla_host_t *ha){	int	rval;	static mbx_cmd_t mc;	mbx_cmd_t *mcp = &mc;	DEBUG12(printk("%s: disable adapter %d\n", __func__, (int)ha->host_no);)	/* Wait for a ready state from the adapter */	while (!ha->init_done || ha->dpc_active) {		set_current_state(TASK_INTERRUPTIBLE);		schedule_timeout(HZ);	}	/* Disable IP support */	ha->flags.enable_ip = FALSE;	mcp->mb[0] = MBC_DISABLE_IP;	mcp->out_mb = MBX_0;	mcp->in_mb = MBX_0;	mcp->tov = 30;	mcp->flags = 0;	rval = qla2x00_mailbox_command(ha, mcp);	if (rval == QL_STATUS_SUCCESS) {		/* IP disabled successful */		DEBUG12(printk(KERN_INFO				"%s: successful\n", __func__);)	}	else {		DEBUG12(printk(KERN_WARNING				"%s: MBC_DISABLE_IP failed\n", __func__);)	}	/* Reset IP parameters */	ha->rec_entries_in = 0;	ha->rec_entries_out = 0;	ha->notify_routine = NULL;}/** * qla2x00_add_buffers() - Adds buffers to the receive buffer queue. * @ha: SCSI driver HA context * @rec_count: The number of receive buffers to add to the queue * @ha_locked: Flag indicating if the function is called with the hardware lock * * This routine is called by the IP driver to pass new buffers to the receive * buffer queue. */static voidqla2x00_add_buffers(scsi_qla_host_t *ha, uint16_t rec_count, int ha_locked){	int		i;	uint16_t	rec_in;	uint16_t	handle;	unsigned long	flags = 0;	device_reg_t	*reg;	struct risc_rec_entry *risc_rec_q;	struct buffer_cb *bcbs;	flags = 0;	risc_rec_q = ha->risc_rec_q;	rec_in = ha->rec_entries_in;	bcbs = ha->receive_buffers;	/* Set RISC owns buffer flag on new entries */	for (i = 0; i < rec_count; i++) {		handle = risc_rec_q[rec_in].handle;		set_bit(BCB_RISC_OWNS_BUFFER, &(bcbs[handle].state));		if (rec_in < IP_BUFFER_QUEUE_DEPTH - 1)			rec_in++;		else			rec_in = 0;	}		/* Update RISC buffer pointer */	if (!ha_locked)		spin_lock_irqsave(&ha->hardware_lock, flags);	reg = ha->iobase;	WRT_REG_WORD(&reg->mailbox8, rec_in);	ha->rec_entries_in = rec_in;	if (!ha_locked)		spin_unlock_irqrestore(&ha->hardware_lock, flags);}/** * qla2x00_send_packet() - Transmit a send_cb. * @ha: SCSI driver HA context * @scb: The send_cb structure to send * * This routine is called by the IP driver to pass @scb (IP packet) to the ISP * for transmission. * * Returns QL_STATUS_SUCCESS if @scb was sent, QL_STATUS_RESOURCE_ERROR if the * RISC was too busy to send, or QL_STATUS_ERROR. */static intqla2x00_send_packet(scsi_qla_host_t *ha, struct send_cb *scb){	int		i;	uint16_t	cnt;	uint16_t	temp;	uint32_t	handle;	unsigned long	flags;	struct ip_cmd_entry *ipcmd_entry;	struct sk_buff	*skb;	device_reg_t	*reg;	DEBUG12(printk("%s: enter\n", __func__);)	skb = scb->skb;	reg = ha->iobase;	/* Check adapter state */	if (!ha->flags.online) {		return (QL_STATUS_ERROR);	}	/* Send marker if required */	if (ha->marker_needed != 0) {		if(qla2x00_marker(ha, 0, 0, MK_SYNC_ALL) != QLA2X00_SUCCESS) {			printk(KERN_WARNING				"%s: Unable to issue marker.\n",				__func__);			return (QL_STATUS_ERROR);		}		ha->marker_needed = 0;	}	/* Acquire ring specific lock */	spin_lock_irqsave(&ha->hardware_lock, flags);	if (ha->req_q_cnt < 4) {		/* Update number of free request entries */#if defined(ISP2200)		cnt = qla2x00_debounce_register(&reg->mailbox4);#else		cnt = qla2x00_debounce_register(&reg->req_q_out);#endif		if (ha->req_ring_index < cnt)			ha->req_q_cnt = cnt - ha->req_ring_index;		else			ha->req_q_cnt = REQUEST_ENTRY_CNT -						(ha->req_ring_index - cnt);	}	if (ha->req_q_cnt >= 4) {		/* Get tag handle for command */		handle = ha->current_scb_q_idx;		for (i = 0; i < MAX_SEND_PACKETS; i++) {			handle++;			if (handle == MAX_SEND_PACKETS)				handle = 0;			if (ha->active_scb_q[handle] == NULL) {				ha->current_scb_q_idx = handle;				goto found_handle;			}		}	}	/* Low on resources, try again later */	spin_unlock_irqrestore(&ha->hardware_lock, flags);	printk(KERN_WARNING		"%s: Low on resources, try again later...\n",		__func__);	return (QL_STATUS_RESOURCE_ERROR);found_handle:	/* Build ISP command packet */	ipcmd_entry = (struct ip_cmd_entry *)ha->request_ring_ptr;	ipcmd_entry->entry_type = ET_IP_COMMAND_64;	ipcmd_entry->entry_count = 1;	ipcmd_entry->sys_define = 0;	ipcmd_entry->entry_status = 0;	ipcmd_entry->handle = handle;	ipcmd_entry->reserved_1 = 0;	/* Get destination loop ID for packet */	if (!qla2x00_get_ip_loopid(ha, scb->header, &ipcmd_entry->loop_id)) {		/* Failed to get loop ID, convert packet to ARP */		if (qla2x00_convert_to_arp(ha, scb)) {			/* Broadcast ARP */			ipcmd_entry->loop_id = BROADCAST;		}		else {			/* Return packet */			spin_unlock_irqrestore(&ha->hardware_lock, flags);			printk(KERN_WARNING				"%s: Unable to determine loop id for "				"destination.\n",				__func__);			return (QL_STATUS_ERROR);		}	}	ipcmd_entry->timeout = 5;	ipcmd_entry->control_flags = CF_WRITE;	ipcmd_entry->reserved_2 = 0;	ipcmd_entry->service_class = 0;	ipcmd_entry->data_seg_count = 2;	ipcmd_entry->ds.data_segs64[0].address[0] = LS_64BITS(scb->header_dma);	ipcmd_entry->ds.data_segs64[0].address[1] = MS_64BITS(scb->header_dma);	ipcmd_entry->ds.data_segs64[0].length = sizeof(struct packet_header);	scb->skb_data_dma = pci_map_single(ha->pdev,					skb->data, skb->len,					PCI_DMA_TODEVICE);	ipcmd_entry->ds.data_segs64[1].address[0] =					LS_64BITS(scb->skb_data_dma);	ipcmd_entry->ds.data_segs64[1].address[1] =					MS_64BITS(scb->skb_data_dma);	ipcmd_entry->ds.data_segs64[1].length = skb->len;	ipcmd_entry->byte_count = skb->len + sizeof(struct packet_header);	/* Adjust ring index. */	ha->req_ring_index++;	if (ha->req_ring_index == REQUEST_ENTRY_CNT) {		ha->req_ring_index = 0;		ha->request_ring_ptr = ha->request_ring;	} else		ha->request_ring_ptr++;	ha->ipreq_cnt++;	ha->req_q_cnt--;	ha->active_scb_q[handle] = scb;	/* Set chip new ring index. */#if defined(ISP2200)	/* Added from 64bit start */	temp = CACHE_FLUSH(&reg->mailbox4);	WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);#else	/* Added from 64bit start */	temp = CACHE_FLUSH(&reg->req_q_in);	WRT_REG_WORD(&reg->req_q_in, ha->req_ring_index);#endif	spin_unlock_irqrestore(&ha->hardware_lock, flags);	return (QL_STATUS_SUCCESS);}/** * qla2x00_tx_timeout() - Handle transmission timeout. * @ha: SCSI driver HA context * * This routine is called by the IP driver to handle packet transmission * timeouts. * * Returns QL_STATUS_SUCCESS if timeout handling completed successfully. */static intqla2x00_tx_timeout(scsi_qla_host_t *ha){	/* TODO: complete interface */	/* Reset RISC firmware for basic recovery */	printk(KERN_WARNING		"%s: A transmission timeout occured - aborting ISP\n",		__func__);	set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);	return (QL_STATUS_SUCCESS);}

⌨️ 快捷键说明

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