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

📄 qla_gs.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * QLogic Fibre Channel HBA Driver * Copyright (c)  2003-2005 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */#include "qla_def.h"static inline struct ct_sns_req *qla2x00_prep_ct_req(struct ct_sns_req *, uint16_t, uint16_t);static inline struct sns_cmd_pkt *qla2x00_prep_sns_cmd(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t);static int qla2x00_sns_ga_nxt(scsi_qla_host_t *, fc_port_t *);static int qla2x00_sns_gid_pt(scsi_qla_host_t *, sw_info_t *);static int qla2x00_sns_gpn_id(scsi_qla_host_t *, sw_info_t *);static int qla2x00_sns_gnn_id(scsi_qla_host_t *, sw_info_t *);static int qla2x00_sns_rft_id(scsi_qla_host_t *);static int qla2x00_sns_rnn_id(scsi_qla_host_t *);/** * qla2x00_prep_ms_iocb() - Prepare common MS/CT IOCB fields for SNS CT query. * @ha: HA context * @req_size: request size in bytes * @rsp_size: response size in bytes * * Returns a pointer to the @ha's ms_iocb. */void *qla2x00_prep_ms_iocb(scsi_qla_host_t *ha, uint32_t req_size, uint32_t rsp_size){	ms_iocb_entry_t *ms_pkt;	ms_pkt = ha->ms_iocb;	memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));	ms_pkt->entry_type = MS_IOCB_TYPE;	ms_pkt->entry_count = 1;	SET_TARGET_ID(ha, ms_pkt->loop_id, SIMPLE_NAME_SERVER);	ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG);	ms_pkt->timeout = __constant_cpu_to_le16(25);	ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);	ms_pkt->total_dsd_count = __constant_cpu_to_le16(2);	ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);	ms_pkt->req_bytecount = cpu_to_le32(req_size);	ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));	ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));	ms_pkt->dseg_req_length = ms_pkt->req_bytecount;	ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));	ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));	ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;	return (ms_pkt);}/** * qla24xx_prep_ms_iocb() - Prepare common CT IOCB fields for SNS CT query. * @ha: HA context * @req_size: request size in bytes * @rsp_size: response size in bytes * * Returns a pointer to the @ha's ms_iocb. */void *qla24xx_prep_ms_iocb(scsi_qla_host_t *ha, uint32_t req_size, uint32_t rsp_size){	struct ct_entry_24xx *ct_pkt;	ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb;	memset(ct_pkt, 0, sizeof(struct ct_entry_24xx));	ct_pkt->entry_type = CT_IOCB_TYPE;	ct_pkt->entry_count = 1;	ct_pkt->nport_handle = __constant_cpu_to_le16(NPH_SNS);	ct_pkt->timeout = __constant_cpu_to_le16(25);	ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);	ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1);	ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);	ct_pkt->cmd_byte_count = cpu_to_le32(req_size);	ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));	ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));	ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;	ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));	ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));	ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;	return (ct_pkt);}/** * qla2x00_prep_ct_req() - Prepare common CT request fields for SNS query. * @ct_req: CT request buffer * @cmd: GS command * @rsp_size: response size in bytes * * Returns a pointer to the intitialized @ct_req. */static inline struct ct_sns_req *qla2x00_prep_ct_req(struct ct_sns_req *ct_req, uint16_t cmd, uint16_t rsp_size){	memset(ct_req, 0, sizeof(struct ct_sns_pkt));	ct_req->header.revision = 0x01;	ct_req->header.gs_type = 0xFC;	ct_req->header.gs_subtype = 0x02;	ct_req->command = cpu_to_be16(cmd);	ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4);	return (ct_req);}static intqla2x00_chk_ms_status(scsi_qla_host_t *ha, ms_iocb_entry_t *ms_pkt,    struct ct_sns_rsp *ct_rsp, const char *routine){	int rval;	uint16_t comp_status;	rval = QLA_FUNCTION_FAILED;	if (ms_pkt->entry_status != 0) {		DEBUG2_3(printk("scsi(%ld): %s failed, error status (%x).\n",		    ha->host_no, routine, ms_pkt->entry_status));	} else {		if (IS_QLA24XX(ha) || IS_QLA25XX(ha))			comp_status =			    ((struct ct_entry_24xx *)ms_pkt)->comp_status;		else			comp_status = le16_to_cpu(ms_pkt->status);		switch (comp_status) {		case CS_COMPLETE:		case CS_DATA_UNDERRUN:		case CS_DATA_OVERRUN:		/* Overrun? */			if (ct_rsp->header.response !=			    __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {				DEBUG2_3(printk("scsi(%ld): %s failed, "				    "rejected request:\n", ha->host_no,				    routine));				DEBUG2_3(qla2x00_dump_buffer(				    (uint8_t *)&ct_rsp->header,				    sizeof(struct ct_rsp_hdr)));			} else				rval = QLA_SUCCESS;			break;		default:			DEBUG2_3(printk("scsi(%ld): %s failed, completion "			    "status (%x).\n", ha->host_no, routine,			    comp_status));			break;		}	}	return rval;}/** * qla2x00_ga_nxt() - SNS scan for fabric devices via GA_NXT command. * @ha: HA context * @fcport: fcport entry to updated * * Returns 0 on success. */intqla2x00_ga_nxt(scsi_qla_host_t *ha, fc_port_t *fcport){	int		rval;	ms_iocb_entry_t	*ms_pkt;	struct ct_sns_req	*ct_req;	struct ct_sns_rsp	*ct_rsp;	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {		return (qla2x00_sns_ga_nxt(ha, fcport));	}	/* Issue GA_NXT */	/* Prepare common MS IOCB */	ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GA_NXT_REQ_SIZE, GA_NXT_RSP_SIZE);	/* Prepare CT request */	ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GA_NXT_CMD,	    GA_NXT_RSP_SIZE);	ct_rsp = &ha->ct_sns->p.rsp;	/* Prepare CT arguments -- port_id */	ct_req->req.port_id.port_id[0] = fcport->d_id.b.domain;	ct_req->req.port_id.port_id[1] = fcport->d_id.b.area;	ct_req->req.port_id.port_id[2] = fcport->d_id.b.al_pa;	/* Execute MS IOCB */	rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,	    sizeof(ms_iocb_entry_t));	if (rval != QLA_SUCCESS) {		/*EMPTY*/		DEBUG2_3(printk("scsi(%ld): GA_NXT issue IOCB failed (%d).\n",		    ha->host_no, rval));	} else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "GA_NXT") !=	    QLA_SUCCESS) {		rval = QLA_FUNCTION_FAILED;	} else {		/* Populate fc_port_t entry. */		fcport->d_id.b.domain = ct_rsp->rsp.ga_nxt.port_id[0];		fcport->d_id.b.area = ct_rsp->rsp.ga_nxt.port_id[1];		fcport->d_id.b.al_pa = ct_rsp->rsp.ga_nxt.port_id[2];		memcpy(fcport->node_name, ct_rsp->rsp.ga_nxt.node_name,		    WWN_SIZE);		memcpy(fcport->port_name, ct_rsp->rsp.ga_nxt.port_name,		    WWN_SIZE);		if (ct_rsp->rsp.ga_nxt.port_type != NS_N_PORT_TYPE &&		    ct_rsp->rsp.ga_nxt.port_type != NS_NL_PORT_TYPE)			fcport->d_id.b.domain = 0xf0;		DEBUG2_3(printk("scsi(%ld): GA_NXT entry - "		    "nn %02x%02x%02x%02x%02x%02x%02x%02x "		    "pn %02x%02x%02x%02x%02x%02x%02x%02x "		    "portid=%02x%02x%02x.\n",		    ha->host_no,		    fcport->node_name[0], fcport->node_name[1],		    fcport->node_name[2], fcport->node_name[3],		    fcport->node_name[4], fcport->node_name[5],		    fcport->node_name[6], fcport->node_name[7],		    fcport->port_name[0], fcport->port_name[1],		    fcport->port_name[2], fcport->port_name[3],		    fcport->port_name[4], fcport->port_name[5],		    fcport->port_name[6], fcport->port_name[7],		    fcport->d_id.b.domain, fcport->d_id.b.area,		    fcport->d_id.b.al_pa));	}	return (rval);}/** * qla2x00_gid_pt() - SNS scan for fabric devices via GID_PT command. * @ha: HA context * @list: switch info entries to populate * * NOTE: Non-Nx_Ports are not requested. * * Returns 0 on success. */intqla2x00_gid_pt(scsi_qla_host_t *ha, sw_info_t *list){	int		rval;	uint16_t	i;	ms_iocb_entry_t	*ms_pkt;	struct ct_sns_req	*ct_req;	struct ct_sns_rsp	*ct_rsp;	struct ct_sns_gid_pt_data *gid_data;	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {		return (qla2x00_sns_gid_pt(ha, list));	}	gid_data = NULL;	/* Issue GID_PT */	/* Prepare common MS IOCB */	ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GID_PT_REQ_SIZE, GID_PT_RSP_SIZE);	/* Prepare CT request */	ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GID_PT_CMD,	    GID_PT_RSP_SIZE);	ct_rsp = &ha->ct_sns->p.rsp;	/* Prepare CT arguments -- port_type */	ct_req->req.gid_pt.port_type = NS_NX_PORT_TYPE;	/* Execute MS IOCB */	rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,	    sizeof(ms_iocb_entry_t));	if (rval != QLA_SUCCESS) {		/*EMPTY*/		DEBUG2_3(printk("scsi(%ld): GID_PT issue IOCB failed (%d).\n",		    ha->host_no, rval));	} else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp, "GID_PT") !=	    QLA_SUCCESS) {		rval = QLA_FUNCTION_FAILED;	} else {		/* Set port IDs in switch info list. */		for (i = 0; i < MAX_FIBRE_DEVICES; i++) {			gid_data = &ct_rsp->rsp.gid_pt.entries[i];			list[i].d_id.b.domain = gid_data->port_id[0];			list[i].d_id.b.area = gid_data->port_id[1];			list[i].d_id.b.al_pa = gid_data->port_id[2];			/* Last one exit. */			if (gid_data->control_byte & BIT_7) {				list[i].d_id.b.rsvd_1 = gid_data->control_byte;				break;			}		}		/*		 * If we've used all available slots, then the switch is		 * reporting back more devices than we can handle with this		 * single call.  Return a failed status, and let GA_NXT handle		 * the overload.		 */		if (i == MAX_FIBRE_DEVICES)			rval = QLA_FUNCTION_FAILED;	}	return (rval);}/** * qla2x00_gpn_id() - SNS Get Port Name (GPN_ID) query. * @ha: HA context * @list: switch info entries to populate * * Returns 0 on success. */intqla2x00_gpn_id(scsi_qla_host_t *ha, sw_info_t *list){	int		rval;	uint16_t	i;	ms_iocb_entry_t	*ms_pkt;	struct ct_sns_req	*ct_req;	struct ct_sns_rsp	*ct_rsp;	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {		return (qla2x00_sns_gpn_id(ha, list));	}	for (i = 0; i < MAX_FIBRE_DEVICES; i++) {		/* Issue GPN_ID */		/* Prepare common MS IOCB */		ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GPN_ID_REQ_SIZE,		    GPN_ID_RSP_SIZE);		/* Prepare CT request */		ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GPN_ID_CMD,		    GPN_ID_RSP_SIZE);		ct_rsp = &ha->ct_sns->p.rsp;		/* Prepare CT arguments -- port_id */		ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;		ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;		ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;		/* Execute MS IOCB */		rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,		    sizeof(ms_iocb_entry_t));		if (rval != QLA_SUCCESS) {			/*EMPTY*/			DEBUG2_3(printk("scsi(%ld): GPN_ID issue IOCB failed "			    "(%d).\n", ha->host_no, rval));		} else if (qla2x00_chk_ms_status(ha, ms_pkt, ct_rsp,		    "GPN_ID") != QLA_SUCCESS) {			rval = QLA_FUNCTION_FAILED;		} else {			/* Save portname */			memcpy(list[i].port_name,			    ct_rsp->rsp.gpn_id.port_name, WWN_SIZE);		}		/* Last device exit. */		if (list[i].d_id.b.rsvd_1 != 0)			break;	}	return (rval);}/** * qla2x00_gnn_id() - SNS Get Node Name (GNN_ID) query. * @ha: HA context * @list: switch info entries to populate * * Returns 0 on success. */intqla2x00_gnn_id(scsi_qla_host_t *ha, sw_info_t *list){	int		rval;	uint16_t	i;	ms_iocb_entry_t	*ms_pkt;	struct ct_sns_req	*ct_req;	struct ct_sns_rsp	*ct_rsp;	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {		return (qla2x00_sns_gnn_id(ha, list));	}	for (i = 0; i < MAX_FIBRE_DEVICES; i++) {		/* Issue GNN_ID */		/* Prepare common MS IOCB */		ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GNN_ID_REQ_SIZE,		    GNN_ID_RSP_SIZE);		/* Prepare CT request */		ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GNN_ID_CMD,		    GNN_ID_RSP_SIZE);		ct_rsp = &ha->ct_sns->p.rsp;		/* Prepare CT arguments -- port_id */		ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;		ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;		ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;		/* Execute MS IOCB */		rval = qla2x00_issue_iocb(ha, ha->ms_iocb, ha->ms_iocb_dma,

⌨️ 快捷键说明

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