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 + -
显示快捷键?