📄 tmscsim.c
字号:
/* Append to Query List */static void dc390_Query_append( PSCSICMD cmd, PACB pACB ){ DEBUG0(printk ("DC390: Append cmd %li to Query\n", cmd->pid);) if( !pACB->QueryCnt ) pACB->pQueryHead = cmd; else pACB->pQueryTail->next = cmd; pACB->pQueryTail = cmd; pACB->QueryCnt++; pACB->CmdOutOfSRB++; cmd->next = NULL;}/* Return next cmd from Query list */static PSCSICMD dc390_Query_get ( PACB pACB ){ PSCSICMD pcmd; pcmd = pACB->pQueryHead; if (!pcmd) return pcmd; DEBUG0(printk ("DC390: Get cmd %li from Query\n", pcmd->pid);) pACB->pQueryHead = pcmd->next; pcmd->next = NULL; if (!pACB->pQueryHead) pACB->pQueryTail = NULL; pACB->QueryCnt--; return( pcmd );}/* Return next free SRB */static __inline__ PSRB dc390_Free_get ( PACB pACB ){ PSRB pSRB; pSRB = pACB->pFreeSRB; DEBUG0(printk ("DC390: Get Free SRB %p\n", pSRB);) if( pSRB ) { pACB->pFreeSRB = pSRB->pNextSRB; pSRB->pNextSRB = NULL; } return( pSRB );}/* Insert SRB oin top of free list */static __inline__ void dc390_Free_insert (PACB pACB, PSRB pSRB){ DEBUG0(printk ("DC390: Free SRB %p\n", pSRB);) pSRB->pNextSRB = pACB->pFreeSRB; pACB->pFreeSRB = pSRB;}/* Inserts a SRB to the top of the Waiting list */static __inline__ void dc390_Waiting_insert ( PDCB pDCB, PSRB pSRB ){ DEBUG0(printk ("DC390: Insert pSRB %p cmd %li to Waiting\n", pSRB, pSRB->pcmd->pid);) pSRB->pNextSRB = pDCB->pWaitingSRB; if (!pDCB->pWaitingSRB) pDCB->pWaitLast = pSRB; pDCB->pWaitingSRB = pSRB; pDCB->WaitSRBCnt++;}/* Queue SRB to waiting list */static __inline__ void dc390_Waiting_append ( PDCB pDCB, PSRB pSRB){ DEBUG0(printk ("DC390: Append pSRB %p cmd %li to Waiting\n", pSRB, pSRB->pcmd->pid);) if( pDCB->pWaitingSRB ) pDCB->pWaitLast->pNextSRB = pSRB; else pDCB->pWaitingSRB = pSRB; pDCB->pWaitLast = pSRB; pSRB->pNextSRB = NULL; pDCB->WaitSRBCnt++; pDCB->pDCBACB->CmdInQ++;}static __inline__ void dc390_Going_append (PDCB pDCB, PSRB pSRB){ pDCB->GoingSRBCnt++; DEBUG0(printk("DC390: Append SRB %p to Going\n", pSRB);) /* Append to the list of Going commands */ if( pDCB->pGoingSRB ) pDCB->pGoingLast->pNextSRB = pSRB; else pDCB->pGoingSRB = pSRB; pDCB->pGoingLast = pSRB; /* No next one in sent list */ pSRB->pNextSRB = NULL;};static __inline__ void dc390_Going_remove (PDCB pDCB, PSRB pSRB){ DEBUG0(printk("DC390: Remove SRB %p from Going\n", pSRB);) if (pSRB == pDCB->pGoingSRB) pDCB->pGoingSRB = pSRB->pNextSRB; else { PSRB psrb = pDCB->pGoingSRB; while (psrb && psrb->pNextSRB != pSRB) psrb = psrb->pNextSRB; if (!psrb) { printk (KERN_ERR "DC390: Remove non-ex. SRB %p from Going!\n", pSRB); return; } psrb->pNextSRB = pSRB->pNextSRB; if (pSRB == pDCB->pGoingLast) pDCB->pGoingLast = psrb; } pDCB->GoingSRBCnt--;};/* Moves SRB from Going list to the top of Waiting list */static void dc390_Going_to_Waiting ( PDCB pDCB, PSRB pSRB ){ DEBUG0(printk(KERN_INFO "DC390: Going_to_Waiting (SRB %p) pid = %li\n", pSRB, pSRB->pcmd->pid);) /* Remove SRB from Going */ dc390_Going_remove (pDCB, pSRB); /* Insert on top of Waiting */ dc390_Waiting_insert (pDCB, pSRB); /* Tag Mask must be freed elsewhere ! (KG, 99/06/18) */}/* Moves first SRB from Waiting list to Going list */static __inline__ void dc390_Waiting_to_Going ( PDCB pDCB, PSRB pSRB ){ /* Remove from waiting list */ DEBUG0(printk("DC390: Remove SRB %p from head of Waiting\n", pSRB);) pDCB->pWaitingSRB = pSRB->pNextSRB; if( !pDCB->pWaitingSRB ) pDCB->pWaitLast = NULL; pDCB->WaitSRBCnt--; dc390_Going_append (pDCB, pSRB);}/* 2.0 timer compatibility */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,30) static inline int timer_pending(struct timer_list * timer) { return timer->prev != NULL; } #define time_after(a,b) ((long)(b) - (long)(a) < 0) #define time_before(a,b) time_after(b,a)#endifvoid DC390_waiting_timed_out (unsigned long ptr);/* Sets the timer to wake us up */static void dc390_waiting_timer (PACB pACB, unsigned long to){ if (timer_pending (&pACB->Waiting_Timer)) return; init_timer (&pACB->Waiting_Timer); pACB->Waiting_Timer.function = DC390_waiting_timed_out; pACB->Waiting_Timer.data = (unsigned long)pACB; if (time_before (jiffies + to, pACB->pScsiHost->last_reset)) pACB->Waiting_Timer.expires = pACB->pScsiHost->last_reset + 1; else pACB->Waiting_Timer.expires = jiffies + to + 1; add_timer (&pACB->Waiting_Timer);}/* Send the next command from the waiting list to the bus */static void dc390_Waiting_process ( PACB pACB ){ PDCB ptr, ptr1; PSRB pSRB; if( (pACB->pActiveDCB) || (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) ) return; if (timer_pending (&pACB->Waiting_Timer)) del_timer (&pACB->Waiting_Timer); ptr = pACB->pDCBRunRobin; if( !ptr ) { ptr = pACB->pLinkDCB; pACB->pDCBRunRobin = ptr; } ptr1 = ptr; if (!ptr1) return; do { pACB->pDCBRunRobin = ptr1->pNextDCB; if( !( pSRB = ptr1->pWaitingSRB ) || ( ptr1->MaxCommand <= ptr1->GoingSRBCnt )) ptr1 = ptr1->pNextDCB; else { /* Try to send to the bus */ if( !dc390_StartSCSI(pACB, ptr1, pSRB) ) dc390_Waiting_to_Going (ptr1, pSRB); else dc390_waiting_timer (pACB, HZ/5); break; } } while (ptr1 != ptr); return;}/* Wake up waiting queue */void DC390_waiting_timed_out (unsigned long ptr){ PACB pACB = (PACB)ptr; DC390_IFLAGS DC390_AFLAGS DEBUG0(printk ("DC390: Debug: Waiting queue woken up by timer!\n");) DC390_LOCK_IO; DC390_LOCK_ACB; dc390_Waiting_process (pACB); DC390_UNLOCK_ACB; DC390_UNLOCK_IO;}/*********************************************************************** * Function: static void dc390_SendSRB (PACB pACB, PSRB pSRB) * * Purpose: Send SCSI Request Block (pSRB) to adapter (pACB) * ***********************************************************************/static void dc390_SendSRB( PACB pACB, PSRB pSRB ){ PDCB pDCB; pDCB = pSRB->pSRBDCB; if( (pDCB->MaxCommand <= pDCB->GoingSRBCnt) || (pACB->pActiveDCB) || (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV)) ) { dc390_Waiting_append (pDCB, pSRB); dc390_Waiting_process (pACB); return; }#if 0 if( pDCB->pWaitingSRB ) { dc390_Waiting_append (pDCB, pSRB);/* pSRB = GetWaitingSRB(pDCB); */ /* non-existent */ pSRB = pDCB->pWaitingSRB; /* Remove from waiting list */ pDCB->pWaitingSRB = pSRB->pNextSRB; pSRB->pNextSRB = NULL; if (!pDCB->pWaitingSRB) pDCB->pWaitLast = NULL; }#endif if (!dc390_StartSCSI(pACB, pDCB, pSRB)) dc390_Going_append (pDCB, pSRB); else { dc390_Waiting_insert (pDCB, pSRB); dc390_waiting_timer (pACB, HZ/5); };}/*********************************************************************** * Function: static void dc390_BuildSRB (Scsi_Cmd *pcmd, PDCB pDCB, * PSRB pSRB) * * Purpose: Prepare SRB for being sent to Device DCB w/ command *pcmd * ***********************************************************************/static void dc390_BuildSRB (Scsi_Cmnd* pcmd, PDCB pDCB, PSRB pSRB){ pSRB->pSRBDCB = pDCB; pSRB->pcmd = pcmd; //pSRB->ScsiCmdLen = pcmd->cmd_len; //memcpy (pSRB->CmdBlock, pcmd->cmnd, pcmd->cmd_len); if( pcmd->use_sg ) { pSRB->SGcount = (UCHAR) pcmd->use_sg; pSRB->pSegmentList = (PSGL) pcmd->request_buffer; } else if( pcmd->request_buffer ) { pSRB->SGcount = 1; pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer; pSRB->Segmentx.length = pcmd->request_bufflen; } else pSRB->SGcount = 0; pSRB->SGIndex = 0; pSRB->AdaptStatus = 0; pSRB->TargetStatus = 0; pSRB->MsgCnt = 0; if( pDCB->DevType != TYPE_TAPE ) pSRB->RetryCnt = 1; else pSRB->RetryCnt = 0; pSRB->SRBStatus = 0; pSRB->SRBFlag = 0; pSRB->SRBState = 0; pSRB->TotalXferredLen = 0; pSRB->SGBusAddr = 0; pSRB->SGToBeXferLen = 0; pSRB->ScsiPhase = 0; pSRB->EndMessage = 0; pSRB->TagNumber = 255;};/* Put cmnd from Query to Waiting list and send next Waiting cmnd */static void dc390_Query_to_Waiting (PACB pACB){ Scsi_Cmnd *pcmd; PSRB pSRB; PDCB pDCB; if( pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) return; while (pACB->QueryCnt) { pSRB = dc390_Free_get ( pACB ); if (!pSRB) return; pcmd = dc390_Query_get ( pACB ); if (!pcmd) { dc390_Free_insert (pACB, pSRB); return; }; /* should not happen */ pDCB = dc390_findDCB (pACB, pcmd->target, pcmd->lun); if (!pDCB) { dc390_Free_insert (pACB, pSRB); printk (KERN_ERR "DC390: Command in queue to non-existing device!\n"); pcmd->result = MK_RES(DRIVER_ERROR,DID_ERROR,0,0); DC390_UNLOCK_ACB_NI; pcmd->done (pcmd); DC390_LOCK_ACB_NI; }; dc390_BuildSRB (pcmd, pDCB, pSRB); dc390_Waiting_append ( pDCB, pSRB ); }}/*********************************************************************** * Function : static int DC390_queue_command (Scsi_Cmnd *cmd, * void (*done)(Scsi_Cmnd *)) * * Purpose : enqueues a SCSI command * * Inputs : cmd - SCSI command, done - callback function called on * completion, with a pointer to the command descriptor. * * Returns : (depending on kernel version) * 2.0.x: always return 0 * 2.1.x: old model: (use_new_eh_code == 0): like 2.0.x * TO BE DONE: * new model: return 0 if successful * return 1 if command cannot be queued (queue full) * command will be inserted in midlevel queue then ... * ***********************************************************************/int DC390_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)){ PDCB pDCB; PSRB pSRB; DC390_AFLAGS PACB pACB = (PACB) cmd->host->hostdata; DEBUG0(/* if(pACB->scan_devices) */ \ printk(KERN_INFO "DC390: Queue Cmd=%02x,Tgt=%d,LUN=%d (pid=%li)\n",\ cmd->cmnd[0],cmd->target,cmd->lun,cmd->pid);) DC390_LOCK_ACB; /* Assume BAD_TARGET; will be cleared later */ cmd->result = DID_BAD_TARGET << 16; /* TODO: Change the policy: Alway accept TEST_UNIT_READY or INQUIRY * commands and alloc a DCB for the device if not yet there. DCB will * be removed in dc390_SRBdone if SEL_TIMEOUT */ if( (pACB->scan_devices == END_SCAN) && (cmd->cmnd[0] != INQUIRY) ) pACB->scan_devices = 0; else if( (pACB->scan_devices) && (cmd->cmnd[0] == READ_6) ) pACB->scan_devices = 0; if ( ( cmd->target >= pACB->pScsiHost->max_id ) || (cmd->lun >= pACB->pScsiHost->max_lun) ) {/* printk ("DC390: Ignore target %d lun %d\n", cmd->target, cmd->lun); */ DC390_UNLOCK_ACB; //return (1); done (cmd); return (0); } if( (pACB->scan_devices || cmd->cmnd[0] == TEST_UNIT_READY || cmd->cmnd[0] == INQUIRY) && !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) ) { pACB->scan_devices = 1; dc390_initDCB( pACB, &pDCB, cmd->target, cmd->lun ); if (!pDCB) { printk (KERN_ERR "DC390: kmalloc for DCB failed, target %02x lun %02x\n", cmd->target, cmd->lun); DC390_UNLOCK_ACB; printk ("DC390: No DCB in queue_command!\n");#ifdef USE_NEW_EH return (1);#else done (cmd); return (0);#endif }; } else if( !(pACB->scan_devices) && !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) ) { printk(KERN_INFO "DC390: Ignore target %02x lun %02x\n", cmd->target, cmd->lun); DC390_UNLOCK_ACB; //return (1); done (cmd); return (0); } else { pDCB = dc390_findDCB (pACB, cmd->target, cmd->lun); if (!pDCB) { /* should never happen */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -