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

📄 qla2x00.c

📁 QL2000卡的驱动程序,可以学习驱动的编程. 对于UNIX的I/O操作有帮助!
💻 C
📖 第 1 页 / 共 5 页
字号:
    *   qla2100_info    *    * Description:    *    * Input:    *     host - pointer to Scsi host adapter structure    *    * Returns:    *     Return a text string describing the driver.    **************************************************************************/    const char *    qla2100_info(struct Scsi_Host *host) {        static char qla2100_buffer[255];        char *bp;        scsi_qla_host_t *ha;        qla_boards_t   *bdp;        bp = &qla2100_buffer[0];        ha = (scsi_qla_host_t *)host->hostdata;        bdp = &QLBoardTbl[ha->devnum];        memset(bp, 0, sizeof(qla2100_buffer));        sprintf(bp,        "QLogic %sPCI to Fibre Channel Host Adapter: bus %d device %d irq %d\n"        "        Firmware version: %2d.%02d.%02d, Driver version %s",        (char *)&bdp->bdName[0], ha->pci_bus, (ha->pci_device_fn & 0xf8) >> 3, host->irq,        bdp->fwver[0], bdp->fwver[1], bdp->fwver[2], QLA2100_VERSION);        return(bp);    }    /**************************************************************************    *   qla1200_queuecommand    *    * Description:    *     Queue a command to the controller.    *    * Input:    *     cmd - pointer to Scsi cmd structure    *     fn - pointer to Scsi done function    *    * Returns:    *   0 - Always    *    * Note:    * The mid-level driver tries to ensures that queuecommand never gets invoked    * concurrently with itself or the interrupt handler (although the    * interrupt handler may call this routine as part of request-completion    * handling).    **************************************************************************/    int    qla2100_queuecommand(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *)) {        scsi_qla_host_t *ha;        srb_t  *sp;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)        unsigned long cpu_flags = 0;#endif        struct Scsi_Host *host;        uint32_t        b, t, l;        scsi_lu_t       *q;        uint32_t          handle;        ENTER("qla2100_queuecommand");        COMTRACE('C')        host = cmd->host;        ha = (scsi_qla_host_t *) host->hostdata;        /* Get our SCSI request pointer        * SCp always point to it - see definition in qla2100.h.        */        sp = (srb_t *) CMD_SP(cmd);        sp->cmd =  cmd;        cmd->scsi_done = fn;        /* If we not trying to do a recovery procedure of some sort        * then this is probably a new command.        */        if( cmd->flags == 0 &&        cmd->retries == 0 )            sp->flags = 0;        DEBUG5(qla2100_print_scsi_cmd(cmd);)        DEBUG5(sprintf(debug_buff,"qla2100_queuecmd: pid=%d, opcode=%d, timeout=%d\n",cmd->pid,cmd->cmnd[0],CMD_TIMEOUT(cmd));)        DEBUG5(qla2100_print(debug_buff);)        /* Generate LU queue on bus, target, LUN */        b = SCSI_BUS_32(cmd);        t = SCSI_TCN_32(cmd);        l = SCSI_LUN_32(cmd);        /*        * We found all the devices at LIP time, and created a device        * table for them, so we only need to check the table to see        * if the device is present. if PORT_AVAILABLE or PORT_UNUSED        * then no target exists.        *        * We return DID_NO_CONNECT if the loop is down after loop down        * timer has expired.        */        if( TGT_Q(ha,b,t) == NULL ||           (TGT_Q(ha,b,t) && TGT_Q(ha,b,t)->loop_id > LAST_SNS_LOOP_ID)  ) {            DEBUG2(printk("scsi(%2d:%2d:%2d:%2d): port unavailable\n",(int)ha->host_no,b,t,l);)            CMD_RESULT(sp->cmd) = DID_NO_CONNECT << 16;            qla2100_callback(ha,sp,FALSE);            LEAVE("qla2100_queuecommand");            return(0);        }        /* v218b4 */         if (ha->loop_down_timer == 0 &&             ha->loop_state == LOOP_DOWN ){  /* 01/21/00 DG */            DEBUG2(printk("scsi(%2d:%2d:%2d:%2d): Loop down - returning pid=%ld \n",(int)ha->host_no,b,t,l,cmd->pid);)            CMD_RESULT(sp->cmd) = DID_NO_CONNECT << 16;            ha->flags.done_requests_needed = TRUE;            qla2100_done_q_put(ha, sp, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);            LEAVE("qla2100_queuecommand");            return(0);        }        /*        * Allocate a LUN/DEVICE queue from this request if we haven't        * already did it on a previous command.        */        if( (q = GET_LU_Q(ha, b, t,l)) == NULL ) {            DRIVER_LOCK            if( (q = qla2100_lun_alloc()) == NULL ) {                CMD_RESULT(sp->cmd) = DID_RETRY << 16;                qla2100_callback(ha,sp,FALSE);                return(0);            }            LU_Q(ha, b, t, l) = q;            DEBUG(sprintf(debug_buff,"Allocate new device queue 0x%x\n",q));            DEBUG(qla2100_print(debug_buff));            DRIVER_UNLOCK        }        /* Set an invalid handle until we issue the command to ISP */        /* then we will set the real handle value.                 */        handle = INVALID_HANDLE;        CMD_HANDLE(cmd) = (unsigned char *)handle;        /* Bookkeeping information */        sp->r_start = jiffies;       /* time the request was recieved */        sp->u_start = 0;#if QLA2100_EXT_TIMEOUT        /* Extend timeout for this request */        qla2100_extend_timeout(cmd,60*HZ);#endif        /*        * SCSI Kluge        * ========        * Whenever, we need to wait for an event such as loop down        * (i.e. loop_down_timer ) or port down (i.e. LUN request qeueue is        * suspended) then we will recycle new commands back to the SCSI layer.        * We do this because this is normally a temporary condition and we don't        * want the mid-level scsi.c driver to get upset and start aborting        * commands.        * The timeout value is extracted from the command minus 1-second        * and put on a retry queue (watchdog). Once the command timeout it        * is returned to the mid-level with a BUSY status, so the mid-level        * will retry it. This process continues until the LOOP DOWN time        * expires or the condition goes away.        */        if( ha->loop_down_timer ||        ha->loop_state ==  LOOP_DOWN ||        ha->loop_state != LOOP_READY ||        (q->q_flag & QLA2100_QSUSP) ) {            /* Insert command into watchdog queue */            qla2100_timeout_insert(ha, sp);            LEAVE("qla2100_queuecommand");            return (0);        }        /* Set retry count if this is a new command */        if( sp->flags == 0 &&        !(q->q_flag & QLA2100_QSUSP) ) {#if 0            sp->port_down_retry_count = ha->port_down_retry_count - 1;#endif            sp->retry_count = ha->retry_count;            DEBUG3(sprintf(debug_buff,"qla2100: Set retry counts =0x%x,0x%x\n\r",sp->port_down_retry_count,sp->retry_count));            DEBUG3(qla2100_print(debug_buff));        }        /* No timeout necessary, because the upper layer is doing it for us */        sp->wdg_time = 0;        /* add the command to our queue */        ha->qthreads++;        qla2100_putq_t(q,sp);        DEBUG5(sprintf(debug_buff,"qla2100_queuecmd: queue pid=%d, hndl=0x%x\n\r",cmd->pid,handle));        DEBUG5(qla2100_print(debug_buff));        /* send command to adapter */        qla2100_restart_queues(ha,FALSE);        COMTRACE('c')        LEAVE("qla2100_queuecommand");        return (0);    }    /**************************************************************************    *   qla1200_abort    *    * Description:    *     Abort the specified SCSI command.    *    * Input:    *     cmd - pointer to Scsi cmd structure    *    * Returns:    **************************************************************************/    int    qla2100_abort(Scsi_Cmnd *cmd) {        scsi_qla_host_t *ha;        srb_t  *sp;        srb_t  *rp, *rp_next;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)        unsigned long cpu_flags = 0;#endif        struct Scsi_Host *host;        uint32_t        b, t, l;        scsi_lu_t       *q;        int return_status = SCSI_ABORT_SUCCESS;        int found = 0;        int i;        uint32_t     handle;        uint16_t    data;        ENTER("qla2100_abort");        COMTRACE('A')        ha = (scsi_qla_host_t *) cmd->host->hostdata;        host = cmd->host;        DRIVER_LOCK        /* Get the SCSI request ptr */        sp = (srb_t *) CMD_SP(cmd);        /*        * if the handle is NULL then we already completed the command.        * We always give the handle a value of "INVALID_HANDLE" when        * we received it.        */        if( (uint32_t) CMD_HANDLE(cmd) == 0L ) {            DRIVER_UNLOCK#if  STOP_ON_ABORT            qla2100_panic("qla2100_abort",ha->host);#endif            return(SCSI_ABORT_NOT_RUNNING);  /* no action - we don't have command */        }        /* Check for a pending interrupt. */        data = qla2100_debounce_register(&ha->iobase->istatus);        if( !(ha->flags.in_isr) && (data & RISC_INT) ) {            /* Add any completed commands in the done queue */            qla2100_isr(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);        }        /*        * if no LUN queue then something is very wrong!!!        */        handle = (uint32_t) CMD_HANDLE(cmd);        /* Generate LU queue on bus, target, LUN */        b = SCSI_BUS_32(cmd);        t = SCSI_TCN_32(cmd);        l = SCSI_LUN_32(cmd);        if( (q = GET_LU_Q(ha, b, t, l)) == NULL ) {            COMTRACE('a')            DRIVER_UNLOCK            printk(KERN_WARNING "qla2100 (%d:%d:%d): No LUN queue for the specified device\n",(int)b,(int)t,(int)l);            return(SCSI_ABORT_NOT_RUNNING);  /* no action - we don't have command */        }#if AUTO_ESCALATE_ABORT        if( (sp->flags & SRB_ABORTED) ) {            DRIVER_UNLOCK            DEBUG(qla2100_print("qla2100_abort: Abort escalayted - returning SCSI_ABORT_SNOOZE.\n\r"));            return(SCSI_ABORT_SNOOZE);        }#endif        /*        * if the command ahs a abort pending then tell the upper layer        */        if( (sp->flags & SRB_ABORT_PENDING) ) {            COMTRACE('a')            DRIVER_UNLOCK            if( qla2100_verbose )                printk("scsi(): Command has a pending abort message - ABORT_PENDING.\n");            DEBUG(qla2100_print("qla2100: Command has a pending abort message - ABORT_PENDING.\n\r"));            return(SCSI_ABORT_PENDING);        }        DEBUG(sprintf(debug_buff,"ABORTing command= 0x%x, jiffies = 0x%lx\n",(int)cmd,jiffies);)        DEBUG(qla2100_print(debug_buff);)        DEBUG(qla2100_print_scsi_cmd(cmd));#if  STOP_ON_ABORT#endif        for( rp = ha->retry_q_first; (rp); rp = rp_next ) {            rp_next = rp->s_next;            if( sp != rp )                continue;            qla2100_timeout_remove(ha, sp);            CMD_RESULT(sp->cmd) = DID_BUS_BUSY << 16;            CMD_HANDLE(sp->cmd) = (unsigned char *) NULL;            qla2100_done_q_put(ha, sp, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);            found++;        }        /*        * Our SP pointer points at the command we want to remove from the        * LUN queue providing we haven't already sent it to the adapter.        */        if( found )            return_status = SCSI_ABORT_SUCCESS;        else if( !(sp->flags&SRB_SENT) ) {            found++;            DEBUG(sprintf(debug_buff,"qla2100: Cmd in LUN queue aborted pid %d.\n\r",sp->cmd->pid);)            DEBUG(qla2100_print(debug_buff);)            /* Remove srb from SCSI LU queue. */            qla2100_removeq(q, sp);            sp->flags |=  SRB_ABORTED;            CMD_RESULT(cmd) = DID_ABORT << 16;            qla2100_done_q_put(ha, sp, &ha->done_q_first, &ha->done_q_last);            return_status = SCSI_ABORT_SUCCESS;        } else {  /* find the command in our active list */            for( i = 1; i < MAX_OUTSTANDING_COMMANDS; i++ ) {                if( sp == ha->outstanding_cmds[i] ) {                    found++;                    DEBUG(sprintf(debug_buff,"qla2100: RISC aborting pid %d command.\n\r",sp->cmd->pid);)                    DEBUG(qla2100_print(debug_buff);)                    DEBUG(qla2100_print_scsi_cmd(cmd));                    DEBUG(qla2100_print_q_info(q);)                    if( qla2100_abort_command(ha,sp) )                        return_status = SCSI_ABORT_NOT_RUNNING;  /* no action */                    else                        return_status = SCSI_ABORT_PENDING;                    break;                }            }        }#if  STOP_ON_ABORT        qla2100_panic("qla2100_abort",ha->host);#endif        if( found == 0 )            return_status = SCSI_ABORT_NOT_RUNNING;  /* no action */        DEBUG(sprintf(de

⌨️ 快捷键说明

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