i91uscsi.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,185 行 · 第 1/5 页
C
2,185 行
} /* Check pending SCB */ if (tul_find_first_pend_scb(pCurHcb) == NULL) { return 1; /* return to OS, enable interrupt */ } } /* End of for loop */ /* statement won't reach here */}/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ *//***************************************************************************//***************************************************************************//***************************************************************************//***************************************************************************//***************************************************************************/void tulip_scsi(HCS * pCurHcb){ SCB *pCurScb; TCS *pCurTcb; /* make sure to service interrupt asap */ if ((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0)) & TSS_INT_PENDING) { pCurHcb->HCS_Phase = pCurHcb->HCS_JSStatus0 & TSS_PH_MASK; pCurHcb->HCS_JSStatus1 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1); pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt); if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) { /* SCSI bus reset detected */ int_tul_scsi_rst(pCurHcb); return; } if (pCurHcb->HCS_JSInt & TSS_RESEL_INT) { /* if selected/reselected interrupt */ if (int_tul_resel(pCurHcb) == 0) tul_next_state(pCurHcb); return; } if (pCurHcb->HCS_JSInt & TSS_SEL_TIMEOUT) { int_tul_busfree(pCurHcb); return; } if (pCurHcb->HCS_JSInt & TSS_DISC_INT) { /* BUS disconnection */ int_tul_busfree(pCurHcb); /* unexpected bus free or sel timeout */ return; } if (pCurHcb->HCS_JSInt & (TSS_FUNC_COMP | TSS_BUS_SERV)) { /* func complete or Bus service */ if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) tul_next_state(pCurHcb); return; } } if (pCurHcb->HCS_ActScb != NULL) return; if ((pCurScb = tul_find_first_pend_scb(pCurHcb)) == NULL) return; /* program HBA's SCSI ID & target SCSI ID */ TUL_WR(pCurHcb->HCS_Base + TUL_SScsiId, (pCurHcb->HCS_SCSI_ID << 4) | (pCurScb->SCB_Target & 0x0F)); if (pCurScb->SCB_Opcode == ExecSCSI) { pCurTcb = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target]; if (pCurScb->SCB_TagMsg) pCurTcb->TCS_DrvFlags |= TCF_DRV_EN_TAG; else pCurTcb->TCS_DrvFlags &= ~TCF_DRV_EN_TAG; TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurTcb->TCS_JS_Period); if ((pCurTcb->TCS_Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) { /* do wdtr negotiation */ tul_select_atn_stop(pCurHcb, pCurScb); } else { if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) { /* do sync negotiation */ tul_select_atn_stop(pCurHcb, pCurScb); } else { if (pCurScb->SCB_TagMsg) tul_select_atn3(pCurHcb, pCurScb); else tul_select_atn(pCurHcb, pCurScb); } } if (pCurScb->SCB_Flags & SCF_POLL) { while (wait_tulip(pCurHcb) != -1) { if (tul_next_state(pCurHcb) == -1) break; } } } else if (pCurScb->SCB_Opcode == BusDevRst) { tul_select_atn_stop(pCurHcb, pCurScb); pCurScb->SCB_NxtStat = 8; if (pCurScb->SCB_Flags & SCF_POLL) { while (wait_tulip(pCurHcb) != -1) { if (tul_next_state(pCurHcb) == -1) break; } } } else if (pCurScb->SCB_Opcode == AbortCmd) { ULONG srbp; srbp = (ULONG) pCurScb->SCB_Srb;/* 08/03/98 */ if (tul_abort_srb(pCurHcb, srbp) != 0) { tul_unlink_pend_scb(pCurHcb, pCurScb); tul_release_scb(pCurHcb, pCurScb); } else { pCurScb->SCB_Opcode = BusDevRst; tul_select_atn_stop(pCurHcb, pCurScb); pCurScb->SCB_NxtStat = 8; }/* 08/03/98 */ } else { tul_unlink_pend_scb(pCurHcb, pCurScb); pCurScb->SCB_HaStat = 0x16; /* bad command */ tul_append_done_scb(pCurHcb, pCurScb); } return;}/***************************************************************************/int tul_next_state(HCS * pCurHcb){ int next; next = pCurHcb->HCS_ActScb->SCB_NxtStat; for (;;) { switch (next) { case 1: next = tul_state_1(pCurHcb); break; case 2: next = tul_state_2(pCurHcb); break; case 3: next = tul_state_3(pCurHcb); break; case 4: next = tul_state_4(pCurHcb); break; case 5: next = tul_state_5(pCurHcb); break; case 6: next = tul_state_6(pCurHcb); break; case 7: next = tul_state_7(pCurHcb); break; case 8: return (tul_bus_device_reset(pCurHcb)); default: return (tul_bad_seq(pCurHcb)); } if (next <= 0) return next; }}/***************************************************************************//* sTate after selection with attention & stop */int tul_state_1(HCS * pCurHcb){ SCB *pCurScb = pCurHcb->HCS_ActScb; TCS *pCurTcb = pCurHcb->HCS_ActTcs;#if DEBUG_STATE printk("-s1-");#endif tul_unlink_pend_scb(pCurHcb, pCurScb); tul_append_busy_scb(pCurHcb, pCurScb); TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0); /* ATN on */ if (pCurHcb->HCS_Phase == MSG_OUT) { TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, (TSC_EN_BUS_IN | TSC_HW_RESELECT)); TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident); if (pCurScb->SCB_TagMsg) { TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagMsg); TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagId); } if ((pCurTcb->TCS_Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) { pCurTcb->TCS_Flags |= TCF_WDTR_DONE; TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND); TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 2); /* Extended msg length */ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3); /* Sync request */ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1); /* Start from 16 bits */ } else if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) { pCurTcb->TCS_Flags |= TCF_SYNC_DONE; TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND); TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3); /* extended msg length */ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1); /* sync request */ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, tul_rate_tbl[pCurTcb->TCS_Flags & TCF_SCSI_RATE]); TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MAX_OFFSET); /* REQ/ACK offset */ } TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); if (wait_tulip(pCurHcb) == -1) return (-1); } TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7))); return (3);}/***************************************************************************//* state after selection with attention *//* state after selection with attention3 */int tul_state_2(HCS * pCurHcb){ SCB *pCurScb = pCurHcb->HCS_ActScb; TCS *pCurTcb = pCurHcb->HCS_ActTcs;#if DEBUG_STATE printk("-s2-");#endif tul_unlink_pend_scb(pCurHcb, pCurScb); tul_append_busy_scb(pCurHcb, pCurScb); TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0); if (pCurHcb->HCS_JSStatus1 & TSS_CMD_PH_CMP) { return (4); } TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7))); return (3);}/***************************************************************************//* state before CDB xfer is done */int tul_state_3(HCS * pCurHcb){ SCB *pCurScb = pCurHcb->HCS_ActScb; TCS *pCurTcb = pCurHcb->HCS_ActTcs; int i;#if DEBUG_STATE printk("-s3-");#endif for (;;) { switch (pCurHcb->HCS_Phase) { case CMD_OUT: /* Command out phase */ for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++) TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]); TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); if (wait_tulip(pCurHcb) == -1) return (-1); if (pCurHcb->HCS_Phase == CMD_OUT) { return (tul_bad_seq(pCurHcb)); } return (4); case MSG_IN: /* Message in phase */ pCurScb->SCB_NxtStat = 3; if (tul_msgin(pCurHcb) == -1) return (-1); break; case STATUS_IN: /* Status phase */ if (tul_status_msg(pCurHcb) == -1) return (-1); break; case MSG_OUT: /* Message out phase */ if (pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) { TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP); /* msg nop */ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); if (wait_tulip(pCurHcb) == -1) return (-1); } else { pCurTcb->TCS_Flags |= TCF_SYNC_DONE; TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND); TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3); /* ext. msg len */ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1); /* sync request */ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, tul_rate_tbl[pCurTcb->TCS_Flags & TCF_SCSI_RATE]); TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MAX_OFFSET); /* REQ/ACK offset */ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); if (wait_tulip(pCurHcb) == -1) return (-1); TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)); } break; default: return (tul_bad_seq(pCurHcb)); } }}/***************************************************************************/int tul_state_4(HCS * pCurHcb){ SCB *pCurScb = pCurHcb->HCS_ActScb;#if DEBUG_STATE printk("-s4-");#endif if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_NO_XF) { return (6); /* Go to state 6 */ } for (;;) { if (pCurScb->SCB_BufLen == 0) return (6); /* Go to state 6 */ switch (pCurHcb->HCS_Phase) { case STATUS_IN: /* Status phase */ if ((pCurScb->SCB_Flags & SCF_DIR) != 0) { /* if direction bit set then report data underrun */ pCurScb->SCB_HaStat = HOST_DO_DU; } if ((tul_status_msg(pCurHcb)) == -1) return (-1); break; case MSG_IN: /* Message in phase */ pCurScb->SCB_NxtStat = 0x4; if (tul_msgin(pCurHcb) == -1) return (-1); break; case MSG_OUT: /* Message out phase */ if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) { pCurScb->SCB_BufLen = 0; pCurScb->SCB_HaStat = HOST_DO_DU; if (tul_msgout_ide(pCurHcb) == -1) return (-1); return (6); /* Go to state 6 */ } else { TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP); /* msg nop */ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); if (wait_tulip(pCurHcb) == -1) return (-1); } break; case DATA_IN: /* Data in phase */ return (tul_xfer_data_in(pCurHcb)); case DATA_OUT: /* Data out phase */ return (tul_xfer_data_out(pCurHcb)); default: return (tul_bad_seq(pCurHcb)); } }}/***************************************************************************//* state after dma xfer done or phase change before xfer done */int tul_state_5(HCS * pCurHcb){ SCB *pCurScb = pCurHcb->HCS_ActScb; long cnt, xcnt; /* cannot use unsigned !! code: if (xcnt < 0) */#if DEBUG_STATE printk("-s5-");#endif/*------ get remaining count -------*/ cnt = TUL_RDLONG(pCurHcb->HCS_Base, TUL_SCnt0) & 0x0FFFFFF; if (TUL_RD(pCurHcb->HCS_Base, TUL_XCmd) & 0x20) { /* ----------------------- DATA_IN ----------------------------- */ /* check scsi parity error */ if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) { pCurScb->SCB_HaStat = HOST_DO_DU; } if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) { /* DMA xfer pending, Send STOP */ /* tell Hardware scsi xfer has been terminated */ TUL_WR(pCurHcb->HCS_Base + TUL_XCtrl, TUL_RD(pCurHcb->HCS_Base, TUL_XCtrl) | 0x80); /* wait until DMA xfer not pending */ while (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND); } } else {/*-------- DATA OUT -----------*/ if ((TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1) & TSS_XFER_CMP) == 0) { if (pCurHcb->HCS_ActTcs->TCS_JS_Period & TSC_WIDE_SCSI) cnt += (TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F) << 1; else cnt += (TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F); } if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) { /* if DMA xfer is pending, abort DMA xfer */ TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT); /* wait Abort DMA xfer done */ while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & XABT) == 0); } if ((cnt == 1) && (pCurHcb->HCS_Phase == DATA_OUT)) { TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); if (wait_tulip(pCurHcb) == -1) { return (-1); } cnt = 0; } else { if ((TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1) & TSS_XFER_CMP) == 0) TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); } } if (cnt == 0) { pCurScb->SCB_BufLen = 0; return (6); /* Go to state 6 */ } /* Update active data pointer */ xcnt = (long) pCurScb->SCB_BufLen - cnt; /* xcnt== bytes already xferred */ pCurScb->SCB_BufLen = (U32) cnt; /* cnt == bytes left to be xferred */ if (pCurScb->SCB_Flags & SCF_SG) { register SG *sgp; ULONG i; sgp = &pCurScb->SCB_SGList[pCurScb->SCB_SGIdx]; for (i = pCurScb->SCB_SGIdx; i < pCurScb->SCB_SGMax; sgp++, i++) { xcnt -= (long) sgp->SG_Len; if (xcnt < 0) { /* this sgp xfer half done */ xcnt += (long) sgp->SG_Len; /* xcnt == bytes xferred in this sgp */ sgp->SG_Ptr += (U32) xcnt; /* new ptr to be xfer */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?