i91uscsi.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,185 行 · 第 1/5 页
C
2,185 行
pCurHcb->HCS_LastBusy = NULL; pTmpScb->SCB_NxtScb = NULL; if (pTmpScb->SCB_TagMsg) pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--; else pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY; }#if DEBUG_QUEUE printk("Pop busy SCB %lx; ", (ULONG) pTmpScb);#endif return (pTmpScb);}/***************************************************************************/void tul_unlink_busy_scb(HCS * pCurHcb, SCB * pCurScb){ SCB *pTmpScb, *pPrevScb;#if DEBUG_QUEUE printk("unlink busy SCB %lx; ", (ULONG) pCurScb);#endif pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy; while (pTmpScb != NULL) { if (pCurScb == pTmpScb) { /* Unlink this SCB */ if (pTmpScb == pCurHcb->HCS_FirstBusy) { if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL) pCurHcb->HCS_LastBusy = NULL; } else { pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb; if (pTmpScb == pCurHcb->HCS_LastBusy) pCurHcb->HCS_LastBusy = pPrevScb; } pTmpScb->SCB_NxtScb = NULL; if (pTmpScb->SCB_TagMsg) pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--; else pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY; break; } pPrevScb = pTmpScb; pTmpScb = pTmpScb->SCB_NxtScb; } return;}/***************************************************************************/SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun){ SCB *pTmpScb, *pPrevScb; WORD scbp_tarlun; pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy; while (pTmpScb != NULL) { scbp_tarlun = (pTmpScb->SCB_Lun << 8) | (pTmpScb->SCB_Target); if (scbp_tarlun == tarlun) { /* Unlink this SCB */ break; } pPrevScb = pTmpScb; pTmpScb = pTmpScb->SCB_NxtScb; }#if DEBUG_QUEUE printk("find busy SCB %lx; ", (ULONG) pTmpScb);#endif return (pTmpScb);}/***************************************************************************/void tul_append_done_scb(HCS * pCurHcb, SCB * scbp){#if DEBUG_QUEUE printk("append done SCB %lx; ", (ULONG) scbp);#endif scbp->SCB_Status = SCB_DONE; scbp->SCB_NxtScb = NULL; if (pCurHcb->HCS_LastDone != NULL) { pCurHcb->HCS_LastDone->SCB_NxtScb = scbp; pCurHcb->HCS_LastDone = scbp; } else { pCurHcb->HCS_FirstDone = scbp; pCurHcb->HCS_LastDone = scbp; }}/***************************************************************************/SCB *tul_find_done_scb(HCS * pCurHcb){ SCB *pTmpScb; if ((pTmpScb = pCurHcb->HCS_FirstDone) != NULL) { if ((pCurHcb->HCS_FirstDone = pTmpScb->SCB_NxtScb) == NULL) pCurHcb->HCS_LastDone = NULL; pTmpScb->SCB_NxtScb = NULL; }#if DEBUG_QUEUE printk("find done SCB %lx; ", (ULONG) pTmpScb);#endif return (pTmpScb);}/***************************************************************************/int tul_abort_srb(HCS * pCurHcb, ULONG srbp){ ULONG flags; SCB *pTmpScb, *pPrevScb; spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) { TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); /* disable Jasmin SCSI Int */ spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); tulip_main(pCurHcb); spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); pCurHcb->HCS_Semaph = 1; TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); return SCSI_ABORT_SNOOZE; } pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend; /* Check Pend queue */ while (pTmpScb != NULL) { /* 07/27/98 */ if (pTmpScb->SCB_Srb == (unsigned char *) srbp) { if (pTmpScb == pCurHcb->HCS_ActScb) { spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); return SCSI_ABORT_BUSY; } else if (pTmpScb == pCurHcb->HCS_FirstPend) { if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL) pCurHcb->HCS_LastPend = NULL; } else { pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb; if (pTmpScb == pCurHcb->HCS_LastPend) pCurHcb->HCS_LastPend = pPrevScb; } pTmpScb->SCB_HaStat = HOST_ABORTED; pTmpScb->SCB_Flags |= SCF_DONE; if (pTmpScb->SCB_Flags & SCF_POST) (*pTmpScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pTmpScb); spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); return SCSI_ABORT_SUCCESS; } pPrevScb = pTmpScb; pTmpScb = pTmpScb->SCB_NxtScb; } pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy; /* Check Busy queue */ while (pTmpScb != NULL) { if (pTmpScb->SCB_Srb == (unsigned char *) srbp) { if (pTmpScb == pCurHcb->HCS_ActScb) { spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); return SCSI_ABORT_BUSY; } else if (pTmpScb->SCB_TagMsg == 0) { spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); return SCSI_ABORT_BUSY; } else { pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--; if (pTmpScb == pCurHcb->HCS_FirstBusy) { if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL) pCurHcb->HCS_LastBusy = NULL; } else { pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb; if (pTmpScb == pCurHcb->HCS_LastBusy) pCurHcb->HCS_LastBusy = pPrevScb; } pTmpScb->SCB_NxtScb = NULL; pTmpScb->SCB_HaStat = HOST_ABORTED; pTmpScb->SCB_Flags |= SCF_DONE; if (pTmpScb->SCB_Flags & SCF_POST) (*pTmpScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pTmpScb); spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); return SCSI_ABORT_SUCCESS; } } pPrevScb = pTmpScb; pTmpScb = pTmpScb->SCB_NxtScb; } spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); return (SCSI_ABORT_NOT_RUNNING);}/***************************************************************************/int tul_bad_seq(HCS * pCurHcb){ SCB *pCurScb; printk("tul_bad_seg c=%d\n", pCurHcb->HCS_Index); if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) { tul_unlink_busy_scb(pCurHcb, pCurScb); pCurScb->SCB_HaStat = HOST_BAD_PHAS; pCurScb->SCB_TaStat = 0; tul_append_done_scb(pCurHcb, pCurScb); } tul_stop_bm(pCurHcb); tul_reset_scsi(pCurHcb, 8); /* 7/29/98 */ return (tul_post_scsi_rst(pCurHcb));}/************************************************************************/int tul_device_reset(HCS * pCurHcb, ULONG pSrb, unsigned int target, unsigned int ResetFlags){ ULONG flags; SCB *pScb; spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); if (ResetFlags & SCSI_RESET_ASYNCHRONOUS) { if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) { TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); /* disable Jasmin SCSI Int */ spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); tulip_main(pCurHcb); spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); pCurHcb->HCS_Semaph = 1; TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); return SCSI_RESET_SNOOZE; } pScb = pCurHcb->HCS_FirstBusy; /* Check Busy queue */ while (pScb != NULL) { if (pScb->SCB_Srb == (unsigned char *) pSrb) break; pScb = pScb->SCB_NxtScb; } if (pScb == NULL) { printk("Unable to Reset - No SCB Found\n"); spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); return SCSI_RESET_NOT_RUNNING; } } if ((pScb = tul_alloc_scb(pCurHcb)) == NULL) { spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); return SCSI_RESET_NOT_RUNNING; } pScb->SCB_Opcode = BusDevRst; pScb->SCB_Flags = SCF_POST; pScb->SCB_Target = target; pScb->SCB_Mode = 0; pScb->SCB_Srb = 0; if (ResetFlags & SCSI_RESET_SYNCHRONOUS) { pScb->SCB_Srb = (unsigned char *) pSrb; } tul_push_pend_scb(pCurHcb, pScb); /* push this SCB to Pending queue */ if (pCurHcb->HCS_Semaph == 1) { TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); /* disable Jasmin SCSI Int */ pCurHcb->HCS_Semaph = 0; spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); tulip_main(pCurHcb); spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); pCurHcb->HCS_Semaph = 1; TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); } spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); return SCSI_RESET_PENDING;}int tul_reset_scsi_bus(HCS * pCurHcb){ ULONG flags; spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); pCurHcb->HCS_Semaph = 0; spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); tul_stop_bm(pCurHcb); tul_reset_scsi(pCurHcb, 2); /* 7/29/98 */ spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); tul_post_scsi_rst(pCurHcb); spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); tulip_main(pCurHcb); spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); pCurHcb->HCS_Semaph = 1; TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); return (SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET);}/************************************************************************/void tul_exec_scb(HCS * pCurHcb, SCB * pCurScb){ ULONG flags; pCurScb->SCB_Mode = 0; pCurScb->SCB_SGIdx = 0; pCurScb->SCB_SGMax = pCurScb->SCB_SGLen; spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); tul_append_pend_scb(pCurHcb, pCurScb); /* Append this SCB to Pending queue *//* VVVVV 07/21/98 */ if (pCurHcb->HCS_Semaph == 1) { TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); /* disable Jasmin SCSI Int */ pCurHcb->HCS_Semaph = 0; spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); tulip_main(pCurHcb); spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags); pCurHcb->HCS_Semaph = 1; TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); } spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags); return;}/***************************************************************************/int tul_isr(HCS * pCurHcb){ /* Enter critical section */ if (TUL_RD(pCurHcb->HCS_Base, TUL_Int) & TSS_INT_PENDING) { if (pCurHcb->HCS_Semaph == 1) { TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); /* Disable Tulip SCSI Int */ pCurHcb->HCS_Semaph = 0; tulip_main(pCurHcb); pCurHcb->HCS_Semaph = 1; TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); return (1); } } return (0);}/***************************************************************************/int tulip_main(HCS * pCurHcb){ SCB *pCurScb; for (;;) { tulip_scsi(pCurHcb); /* Call tulip_scsi */ while ((pCurScb = tul_find_done_scb(pCurHcb)) != NULL) { /* find done entry */ if (pCurScb->SCB_TaStat == QUEUE_FULL) { pCurHcb->HCS_MaxTags[pCurScb->SCB_Target] = pCurHcb->HCS_ActTags[pCurScb->SCB_Target] - 1; pCurScb->SCB_TaStat = 0; tul_append_pend_scb(pCurHcb, pCurScb); continue; } if (!(pCurScb->SCB_Mode & SCM_RSENS)) { /* not in auto req. sense mode */ if (pCurScb->SCB_TaStat == 2) { /* clr sync. nego flag */ if (pCurScb->SCB_Flags & SCF_SENSE) { BYTE len; len = pCurScb->SCB_SenseLen; if (len == 0) len = 1; pCurScb->SCB_BufLen = pCurScb->SCB_SenseLen; pCurScb->SCB_BufPtr = pCurScb->SCB_SensePtr; pCurScb->SCB_Flags &= ~(SCF_SG | SCF_DIR); /* for xfer_data_in *//* pCurScb->SCB_Flags |= SCF_NO_DCHK; */ /* so, we won't report worng direction in xfer_data_in, and won't report HOST_DO_DU in state_6 */ pCurScb->SCB_Mode = SCM_RSENS; pCurScb->SCB_Ident &= 0xBF; /* Disable Disconnect */ pCurScb->SCB_TagMsg = 0; pCurScb->SCB_TaStat = 0; pCurScb->SCB_CDBLen = 6; pCurScb->SCB_CDB[0] = SCSICMD_RequestSense; pCurScb->SCB_CDB[1] = 0; pCurScb->SCB_CDB[2] = 0; pCurScb->SCB_CDB[3] = 0; pCurScb->SCB_CDB[4] = len; pCurScb->SCB_CDB[5] = 0; tul_push_pend_scb(pCurHcb, pCurScb); break; } } } else { /* in request sense mode */ if (pCurScb->SCB_TaStat == 2) { /* check contition status again after sending requset sense cmd 0x3 */ pCurScb->SCB_HaStat = HOST_BAD_PHAS; } pCurScb->SCB_TaStat = 2; } pCurScb->SCB_Flags |= SCF_DONE; if (pCurScb->SCB_Flags & SCF_POST) { (*pCurScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pCurScb); } } /* while */ /* find_active: */ if (TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0) & TSS_INT_PENDING) continue; if (pCurHcb->HCS_ActScb) { /* return to OS and wait for xfer_done_ISR/Selected_ISR */ return 1; /* return to OS, enable interrupt */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?