📄 qla2x00.c
字号:
* 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 + -