qla2x00_ioctl.c

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

C
2,436 行
字号
/****************************************************************************** *                  QLOGIC LINUX SOFTWARE * * QLogic ISP2x00 device driver for Linux 2.4.x * Copyright (C) 2002 Qlogic Corporation * (www.qlogic.com) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. * ******************************************************************************/#define	QLA_PT_CMD_TOV			(30)#define QLA_IOCTL_ACCESS_WAIT_TIME	30 /* seconds */#define QLA_INITIAL_IOCTLMEM_SIZE	(2 * PAGE_SIZE)#define IOCTL_INVALID_STATUS    0xffff#if defined(INTAPI)#include "inioct.h"/* from qla_inioct.c */extern int qla2x00_read_nvram(scsi_qla_host_t *, EXT_IOCTL *, int);extern int qla2x00_update_nvram(scsi_qla_host_t *, EXT_IOCTL *, int);extern int qla2x00_write_nvram_word(scsi_qla_host_t *, uint8_t, uint16_t);extern int qla2x00_send_loopback(scsi_qla_host_t *, EXT_IOCTL *, int);#endifSTATIC int qla2x00_alloc_ioctl_mem(scsi_qla_host_t *);STATIC int qla2x00_get_new_ioctl_dma_mem(scsi_qla_host_t *, uint32_t);STATIC void qla2x00_free_ioctl_mem(scsi_qla_host_t *);/* * Local prototypes */STATIC int qla2x00_find_curr_ha(int, scsi_qla_host_t **);STATIC int qla2x00_aen_reg(scsi_qla_host_t *, EXT_IOCTL *, int);STATIC int qla2x00_aen_get(scsi_qla_host_t *, EXT_IOCTL *, int);STATIC void qla2x00_enqueue_aen(scsi_qla_host_t *, uint16_t, void *);STATIC int qla2x00_query(scsi_qla_host_t *, EXT_IOCTL *, int);STATIC int qla2x00_query_hba_node(scsi_qla_host_t *, EXT_IOCTL *, int);STATIC int qla2x00_query_hba_port(scsi_qla_host_t *, EXT_IOCTL *, int);STATIC int qla2x00_query_disc_port(scsi_qla_host_t *, EXT_IOCTL *, int);STATIC int qla2x00_query_disc_tgt(scsi_qla_host_t *, EXT_IOCTL *, int);STATIC int qla2x00_query_chip(scsi_qla_host_t *, EXT_IOCTL *, int);STATIC int qla2x00_get_data(scsi_qla_host_t *, EXT_IOCTL *, int);STATIC int qla2x00_get_statistics(scsi_qla_host_t *, EXT_IOCTL *, int);STATIC int qla2x00_get_fc_statistics(scsi_qla_host_t *, EXT_IOCTL *, int);STATIC int qla2x00_get_port_summary(scsi_qla_host_t *, EXT_IOCTL *, int);STATIC int qla2x00_query_driver(scsi_qla_host_t *, EXT_IOCTL *, int);STATIC int qla2x00_query_fw(scsi_qla_host_t *, EXT_IOCTL *, int);STATIC int qla2x00_send_fcct(scsi_qla_host_t *, EXT_IOCTL *, int);STATIC int qla2x00_start_ms_cmd(scsi_qla_host_t *, EXT_IOCTL *, srb_t *);STATIC int qla2x00_wwpn_to_scsiaddr(scsi_qla_host_t *, EXT_IOCTL *, int);STATIC int qla2x00_scsi_passthru(scsi_qla_host_t *, EXT_IOCTL *, int);STATIC int qla2x00_sc_scsi_passthru(scsi_qla_host_t *, EXT_IOCTL *, int);STATIC int qla2x00_sc_fc_scsi_passthru(scsi_qla_host_t *, EXT_IOCTL *, int);STATIC int qla2x00_sc_scsi3_passthru(scsi_qla_host_t *, EXT_IOCTL *, int);STATIC int qla2x00_send_els_rnid(scsi_qla_host_t *, EXT_IOCTL *, int);STATIC int qla2x00_get_rnid_params(scsi_qla_host_t *, EXT_IOCTL *, int);STATIC int qla2x00_set_host_data(scsi_qla_host_t *, EXT_IOCTL *, int);STATIC int qla2x00_set_rnid_params(scsi_qla_host_t *, EXT_IOCTL *, int);STATIC void qla2x00_waitq_sem_timeout(unsigned long);STATIC uint8_t qla2x00_get_ioctl_access(scsi_qla_host_t *, uint32_t);STATIC uint8_t qla2x00_release_ioctl_access(scsi_qla_host_t *);STATIC void qla2x00_wait_q_memb_alloc(scsi_qla_host_t *, wait_q_t **);STATIC void qla2x00_wait_q_memb_free(scsi_qla_host_t *, wait_q_t *);STATIC uint8_t qla2x00_wait_q_add(scsi_qla_host_t *, wait_q_t **);STATIC void qla2x00_wait_q_remove(scsi_qla_host_t *, wait_q_t **);/* * qla2x00_ioctl_sleep_done * * Description: *   This is the callback function to wakeup ioctl completion semaphore *   for the ioctl request that is waiting. * * Input: *   sem - pointer to the ioctl completion semaphore. * * Returns: */STATIC voidqla2x00_ioctl_sleep_done(struct semaphore * sem){	DEBUG9(printk("ioctl_sleep: entered.\n");)	if (sem != NULL){		DEBUG9(printk("ioctl_sleep: wake up sem.\n");)		up(sem);	}	DEBUG9(printk("ioctl_sleep: exiting.\n");)}/* * qla2x00_ioctl_sem_init * * Description: *   Initialize the ioctl timer and semaphore used to wait for passthru *   completion. * * Input: *   ha - pointer to scsi_qla_host_t structure used for initialization. * * Returns: *   None. */STATIC voidqla2x00_ioctl_sem_init(scsi_qla_host_t *ha){	init_MUTEX_LOCKED(&ha->ioctl->cmpl_sem);	init_timer(&(ha->ioctl->cmpl_timer));	ha->ioctl->cmpl_timer.data = (unsigned long)&ha->ioctl->cmpl_sem;	ha->ioctl->cmpl_timer.function =	    (void (*)(unsigned long))qla2x00_ioctl_sleep_done;}/* * qla2x00_scsi_pt_done * * Description: *   Resets ioctl progress flag and wakes up the ioctl completion semaphore. * * Input: *   pscsi_cmd - pointer to the passthru Scsi cmd structure which has completed. * * Returns: */STATIC voidqla2x00_scsi_pt_done(Scsi_Cmnd *pscsi_cmd){	struct Scsi_Host *host;	scsi_qla_host_t  *ha;	host = pscsi_cmd->host;	ha = (scsi_qla_host_t *) host->hostdata;	DEBUG9(printk("qla2x00_scsi_pt_done post function called OK\n");)	/* save detail status for IOCTL reporting */	ha->ioctl->SCSIPT_InProgress = 0;	ha->ioctl->ioctl_tov = 0;	up(&ha->ioctl->cmpl_sem);	DEBUG9(printk("qla2x00_scsi_pt_done: exiting.\n");)	return;}/* * qla2x00_fcct_done * * Description: *   Resets FCCT ioctl progress flag and wakes up the ioctl completion *   semaphore. * * Input: *   cmd - pointer to the passthru Scsi cmd structure which has completed. * * Returns: */STATIC voidqla2x00_fcct_done(Scsi_Cmnd *pscsi_cmd){	struct Scsi_Host *host;	scsi_qla_host_t  *ha;	host = pscsi_cmd->host;	ha = (scsi_qla_host_t *) host->hostdata;	DEBUG9(printk("qla2x00_fcct_done post function called OK\n");)	ha->ioctl->FCCT_InProgress = 0;	ha->ioctl->ioctl_tov = 0;	up(&ha->ioctl->cmpl_sem);	DEBUG9(printk("qla2x00_fcct_done: exiting.\n");)			return;}/************************************************************************* * qla2x00_ioctl * * Description: *   Performs additional ioctl requests not satisfied by the upper levels. * * Returns: *   ret  = 0    Success *   ret != 0    Failed; detailed status copied to EXT_IOCTL structure *               if applicable *************************************************************************/intqla2x00_ioctl(Scsi_Device *dev, int cmd, void *arg){	int		mode = 0;	int		rval = 0;	int		ret = EINVAL;	uint8_t		*temp;	uint8_t		tempbuf[8];	uint32_t	i;	uint32_t	status;	static EXT_IOCTL	ext;	PEXT_IOCTL		pext = &ext;	scsi_qla_host_t		*ha;	struct Scsi_Host	*host;	DEBUG9(printk("qla2x00_ioctl: entry to command (%x), arg (%p)\n",		cmd, arg);)	/* Catch any non-exioct ioctls */	if (_IOC_TYPE(cmd) != QLMULTIPATH_MAGIC) {		return (-EINVAL);	}	host = dev->host;	ha = (scsi_qla_host_t *) host->hostdata; /* midlayer chosen instance */	ret = verify_area(VERIFY_READ, (void *)arg, sizeof(EXT_IOCTL));	if (ret) {		DEBUG9_10(printk("qla2x00_ioctl: ERROR VERIFY_READ EXT_IOCTL "		    "sturct. ha=%p.\n", ha);)		return ret;	}	/* copy in application layer EXT_IOCTL */	ret = copy_from_user(pext, arg, sizeof(EXT_IOCTL));	if (ret) {		DEBUG9_10(printk("qla2x00_ioctl: ERROR COPY_FROM_USER "				       "EXT_IOCTL sturct. ha=%p.\n",				       ha);)		return ret;	}	/* check signature of this ioctl */	temp = (uint8_t *) &pext->Signature;	for (i = 0; i < 4; i++, temp++)		tempbuf[i] = *temp;	if ((tempbuf[0] == 'Q') && (tempbuf[1] == 'L') &&	    (tempbuf[2] == 'O') && (tempbuf[3] == 'G'))		status = 0;	else		status = 1;	if (status != 0) {		DEBUG9_10(printk("qla2x00_ioctl: signature did not match. "		    "ha=%p\n", ha);)		pext->Status = EXT_STATUS_INVALID_PARAM;		copy_to_user((void *)arg, (void *)pext, sizeof(EXT_IOCTL));		return EXT_STATUS_ERR;	}	/* check version of this ioctl */	if (pext->Version > EXT_VERSION) {		printk(KERN_WARNING		    "qla2x00: interface version not supported = %d.\n",				pext->Version);		pext->Status = EXT_STATUS_UNSUPPORTED_VERSION;		copy_to_user((void *)arg, (void *)pext, sizeof(EXT_IOCTL));		return EXT_STATUS_ERR;	}	/* check for API setting HBA Instance for subsequent operations */	if (cmd == (int)EXT_CC_STARTIOCTL) {		DEBUG9(printk("qla2x00_ioctl: got startioctl command.\n");)		pext->Instance = num_hosts;		pext->Status = EXT_STATUS_OK;		copy_to_user((void *)arg, (void *)pext, sizeof(EXT_IOCTL));		return EXT_STATUS_OK;	} else if (cmd == (int)EXT_CC_SETINSTANCE) {		/*		 * Since API opens devices once and uses handle for		 * subsequent calls, we keep a parameter to designate		 * the "active HBA" for ioctls.		 */		if (pext->Instance < num_hosts) {			apiHBAInstance = pext->Instance;			/*			 * Return host number in pext->HbaSelect for			 * reference by IOCTL caller.			 */			if (qla2x00_find_curr_ha(apiHBAInstance, &ha) != 0) {				DEBUG9_10(printk("qla2x00_ioctl: ERROR finding "				    "ha in EXT_SETINSTANCE. Instance=%d "				    "num_hosts=%d ha=%p.\n",				    pext->Instance, num_hosts, ha);)				pext->Status = EXT_STATUS_DEV_NOT_FOUND;				copy_to_user(arg, pext, sizeof(EXT_IOCTL));				return EXT_STATUS_ERR;			}			pext->HbaSelect = ha->host_no;			pext->Status = EXT_STATUS_OK;			copy_to_user(arg, pext, sizeof(EXT_IOCTL));			DEBUG9(printk("qla2x00_ioctl: Setting instance to "			    "%d.\n", apiHBAInstance);)			ret = EXT_STATUS_OK;		} else {			DEBUG9_10(printk("qla2x00_ioctl: ERROR EXT_SETINSTANCE."			    " Instance=%d num_hosts=%d ha=%p.\n",			    pext->Instance, num_hosts, ha);)			pext->Status = EXT_STATUS_DEV_NOT_FOUND;			copy_to_user(arg, pext, sizeof(EXT_IOCTL));			ret = EXT_STATUS_ERR;		}		return ret;	}	/*	 * Check for valid apiHBAInstance (set previously by EXT_SETINSTANCE	 * or default 0)  and set ha context for this IOCTL.	 */	if (qla2x00_find_curr_ha(apiHBAInstance, &ha) != 0) {		DEBUG9_10(printk("qla2x00_ioctl: ERROR matching apiHBAInstance "		    "%d to an HBA Instance.\n", apiHBAInstance);)		pext->Status = EXT_STATUS_DEV_NOT_FOUND;		copy_to_user(arg, pext, sizeof(EXT_IOCTL));		return EXT_STATUS_ERR;	}	/*	 * Get permission to process ioctl command. Only one will proceed	 * at a time.	 */	if (qla2x00_get_ioctl_access(ha, QLA_IOCTL_ACCESS_WAIT_TIME) != 0) {		/* error timed out */		DEBUG9_10(printk("qla2x00_ioctl: ERROR timeout getting "		    "ioctl access. Inst=%d.\n", apiHBAInstance);)		pext->Status = EXT_STATUS_BUSY;		copy_to_user(arg, pext, sizeof(EXT_IOCTL));		return EXT_STATUS_ERR;	}	/*	 * Set EXT_IOCTL.HbaSelect to host number for reference by IOCTL	 * caller.	 */	pext->HbaSelect = ha->host_no;	DEBUG9(printk("qla2x00_ioctl: active apiHBAInstance=%d CC=%x SC=%x.\n",	    apiHBAInstance, cmd, pext->SubCode);)	while( test_bit(CFG_ACTIVE, &ha->cfg_flags) || ha->dpc_active ) {		if( signal_pending(current) )			break;   /* get out */		set_current_state(TASK_INTERRUPTIBLE);		schedule_timeout(HZ);	};	switch (cmd) { /* switch on EXT IOCTL COMMAND CODE */	case EXT_CC_QUERY:		DEBUG9(printk("qla2x00_ioctl: got query command.\n");)		rval = qla2x00_query(ha, pext, 0);		ret = (rval == QL_STATUS_SUCCESS) ?		    EXT_STATUS_OK : EXT_STATUS_ERR;		copy_to_user((void *)arg, (void *)pext, sizeof(EXT_IOCTL));		break;	case EXT_CC_GET_DATA:		DEBUG9(printk("qla2x00_ioctl: got get_data command.\n");)		rval = qla2x00_get_data(ha, pext, 0);		ret = (rval == QL_STATUS_SUCCESS) ?		    EXT_STATUS_OK : EXT_STATUS_ERR;		copy_to_user((void *)arg, (void *)pext, sizeof(EXT_IOCTL));		break;	case EXT_CC_SEND_FCCT_PASSTHRU:		DEBUG9(printk("qla2x00_ioctl: got CT passthru cmd.\n"));		rval = qla2x00_send_fcct(ha, pext, 0);		ret = (rval == QL_STATUS_SUCCESS) ?		    EXT_STATUS_OK : EXT_STATUS_ERR;		copy_to_user((void *)arg, (void *)pext, sizeof(EXT_IOCTL));		break;	case EXT_CC_SEND_SCSI_PASSTHRU:		DEBUG9(printk("qla2x00_ioctl: got SCSI passthru cmd.\n"));		rval = qla2x00_scsi_passthru(ha, pext, mode);		ret = (rval == QL_STATUS_SUCCESS) ?		    EXT_STATUS_OK : EXT_STATUS_ERR;		copy_to_user((void *)arg, (void *)pext, sizeof(EXT_IOCTL));		break;	case EXT_CC_REG_AEN:		rval = qla2x00_aen_reg(ha, pext, mode);		ret = (rval == QL_STATUS_SUCCESS) ?		    EXT_STATUS_OK : EXT_STATUS_ERR;		copy_to_user((void *)arg, (void *)pext, sizeof(EXT_IOCTL));		break;	case EXT_CC_GET_AEN:		rval = qla2x00_aen_get(ha, pext, mode);		ret = (rval == QL_STATUS_SUCCESS) ?		    EXT_STATUS_OK : EXT_STATUS_ERR;		copy_to_user((void *)arg, (void *)pext, sizeof(EXT_IOCTL));		break;	case EXT_CC_WWPN_TO_SCSIADDR:		rval = qla2x00_wwpn_to_scsiaddr(ha, pext, 0);		ret = (rval == QL_STATUS_SUCCESS) ?		    EXT_STATUS_OK : EXT_STATUS_ERR;		copy_to_user(arg, pext, sizeof(EXT_IOCTL));		break;	case EXT_CC_SEND_ELS_RNID:		rval = qla2x00_send_els_rnid(ha, pext, mode);		ret = (rval == QL_STATUS_SUCCESS) ?		    EXT_STATUS_OK : EXT_STATUS_ERR;		copy_to_user(arg, pext, sizeof(EXT_IOCTL));		break;	case EXT_CC_SET_DATA:		rval = qla2x00_set_host_data(ha, pext, mode);		ret = (rval == QL_STATUS_SUCCESS) ?		    EXT_STATUS_OK : EXT_STATUS_ERR;		copy_to_user(arg, pext, sizeof(EXT_IOCTL));		break;                                                          #if defined(INTAPI)	case INT_CC_READ_NVRAM:		rval = qla2x00_read_nvram(ha, pext, mode);		ret = (rval == QL_STATUS_SUCCESS) ?		    EXT_STATUS_OK : EXT_STATUS_ERR;		copy_to_user((void *)arg, (void *)pext, sizeof(EXT_IOCTL));		break;	case INT_CC_UPDATE_NVRAM:		rval = qla2x00_update_nvram(ha, pext, mode);		ret = (rval == QL_STATUS_SUCCESS) ?		    EXT_STATUS_OK : EXT_STATUS_ERR;		copy_to_user((void *)arg, (void *)pext, sizeof(EXT_IOCTL));		break;

⌨️ 快捷键说明

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