📄 i91uscsi.c
字号:
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 */ sgp->SG_Len -= (U32) xcnt; /* new len to be xfer */ pCurScb->SCB_BufPtr += ((U32) (i - pCurScb->SCB_SGIdx) << 3); /* new SG table ptr */ pCurScb->SCB_SGLen = (BYTE) (pCurScb->SCB_SGMax - i); /* new SG table len */ pCurScb->SCB_SGIdx = (WORD) i; /* for next disc and come in this loop */ return (4); /* Go to state 4 */ } /* else (xcnt >= 0 , i.e. this sgp already xferred */ } /* for */ return (6); /* Go to state 6 */ } else { pCurScb->SCB_BufPtr += (U32) xcnt; } return (4); /* Go to state 4 */}/***************************************************************************//* state after Data phase */int tul_state_6(HCS * pCurHcb){ SCB *pCurScb = pCurHcb->HCS_ActScb;#if DEBUG_STATE printk("-s6-");#endif for (;;) { switch (pCurHcb->HCS_Phase) { case STATUS_IN: /* Status phase */ if ((tul_status_msg(pCurHcb)) == -1) return (-1); break; case MSG_IN: /* Message in phase */ pCurScb->SCB_NxtStat = 6; if ((tul_msgin(pCurHcb)) == -1) return (-1); break; case MSG_OUT: /* Message out phase */ 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_xpad_in(pCurHcb)); case DATA_OUT: /* Data out phase */ return (tul_xpad_out(pCurHcb)); default: return (tul_bad_seq(pCurHcb)); } }}/***************************************************************************/int tul_state_7(HCS * pCurHcb){ int cnt, i;#if DEBUG_STATE printk("-s7-");#endif /* flush SCSI FIFO */ cnt = TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F; if (cnt) { for (i = 0; i < cnt; i++) TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); } switch (pCurHcb->HCS_Phase) { case DATA_IN: /* Data in phase */ case DATA_OUT: /* Data out phase */ return (tul_bad_seq(pCurHcb)); default: return (6); /* Go to state 6 */ }}/***************************************************************************/int tul_xfer_data_in(HCS * pCurHcb){ SCB *pCurScb = pCurHcb->HCS_ActScb; if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DOUT) { return (6); /* wrong direction */ } TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, pCurScb->SCB_BufLen); TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_DMA_IN); /* 7/25/95 */ if (pCurScb->SCB_Flags & SCF_SG) { /* S/G xfer */ TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, ((ULONG) pCurScb->SCB_SGLen) << 3); TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr); TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_SG_IN); } else { TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, pCurScb->SCB_BufLen); TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr); TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_IN); } pCurScb->SCB_NxtStat = 0x5; return (0); /* return to OS, wait xfer done , let jas_isr come in */}/***************************************************************************/int tul_xfer_data_out(HCS * pCurHcb){ SCB *pCurScb = pCurHcb->HCS_ActScb; if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DIN) { return (6); /* wrong direction */ } TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, pCurScb->SCB_BufLen); TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_DMA_OUT); if (pCurScb->SCB_Flags & SCF_SG) { /* S/G xfer */ TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, ((ULONG) pCurScb->SCB_SGLen) << 3); TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr); TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_SG_OUT); } else { TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, pCurScb->SCB_BufLen); TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr); TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_OUT); } pCurScb->SCB_NxtStat = 0x5; return (0); /* return to OS, wait xfer done , let jas_isr come in */}/***************************************************************************/int tul_xpad_in(HCS * pCurHcb){ SCB *pCurScb = pCurHcb->HCS_ActScb; TCS *pCurTcb = pCurHcb->HCS_ActTcs; if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) { pCurScb->SCB_HaStat = HOST_DO_DU; /* over run */ } for (;;) { if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI) TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 2); else TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1); TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN); if ((wait_tulip(pCurHcb)) == -1) { return (-1); } if (pCurHcb->HCS_Phase != DATA_IN) { TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); return (6); } TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); }}int tul_xpad_out(HCS * pCurHcb){ SCB *pCurScb = pCurHcb->HCS_ActScb; TCS *pCurTcb = pCurHcb->HCS_ActTcs; if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) { pCurScb->SCB_HaStat = HOST_DO_DU; /* over run */ } for (;;) { if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI) TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 2); else TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1); TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 0); TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); if ((wait_tulip(pCurHcb)) == -1) { return (-1); } if (pCurHcb->HCS_Phase != DATA_OUT) { /* Disable wide CPU to allow read 16 bits */ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT); TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); return (6); } }}/***************************************************************************/int tul_status_msg(HCS * pCurHcb){ /* status & MSG_IN */ SCB *pCurScb = pCurHcb->HCS_ActScb; BYTE msg; TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_CMD_COMP); if ((wait_tulip(pCurHcb)) == -1) { return (-1); } /* get status */ pCurScb->SCB_TaStat = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); if (pCurHcb->HCS_Phase == MSG_OUT) { if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) { TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_PARITY); } else { TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP); } TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); return (wait_tulip(pCurHcb)); } if (pCurHcb->HCS_Phase == MSG_IN) { msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) { /* Parity error */ if ((tul_msgin_accept(pCurHcb)) == -1) return (-1); if (pCurHcb->HCS_Phase != MSG_OUT) return (tul_bad_seq(pCurHcb)); TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_PARITY); TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT); return (wait_tulip(pCurHcb)); } if (msg == 0) { /* Command complete */ if ((pCurScb->SCB_TaStat & 0x18) == 0x10) { /* No link support */ return (tul_bad_seq(pCurHcb)); } TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT); return tul_wait_done_disc(pCurHcb); } if ((msg == MSG_LINK_COMP) || (msg == MSG_LINK_FLAG)) { if ((pCurScb->SCB_TaStat & 0x18) == 0x10) return (tul_msgin_accept(pCurHcb)); } } return (tul_bad_seq(pCurHcb));}/***************************************************************************//* scsi bus free */int int_tul_busfree(HCS * pCurHcb){ SCB *pCurScb = pCurHcb->HCS_ActScb; if (pCurScb != NULL) { if (pCurScb->SCB_Status & SCB_SELECT) { /* selection timeout */ tul_unlink_pend_scb(pCurHcb, pCurScb); pCurScb->SCB_HaStat = HOST_SEL_TOUT; tul_append_done_scb(pCurHcb, pCurScb); } else { /* Unexpected bus free */ tul_unlink_busy_scb(pCurHcb, pCurScb); pCurScb->SCB_HaStat = HOST_BUS_FREE; tul_append_done_scb(pCurHcb, pCurScb); } pCurHcb->HCS_ActScb = NULL; pCurHcb->HCS_ActTcs = NULL; } TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); /* Flush SCSI FIFO */ TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT); TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT); /* Enable HW reselect */ return (-1);}/***************************************************************************//* scsi bus reset */int int_tul_scsi_rst(HCS * pCurHcb){ SCB *pCurScb; int i; /* if DMA xfer is pending, abort DMA xfer */ if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & 0x01) { TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO); /* wait Abort DMA xfer done */ while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & 0x04) == 0); TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); } /* Abort all active & disconnected scb */ while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) { pCurScb->SCB_HaStat = HOST_BAD_PHAS; tul_append_done_scb(pCurHcb, pCurScb); } pCurHcb->HCS_ActScb = NULL; pCurHcb->HCS_ActTcs = NULL; /* clr sync nego. done flag */ for (i = 0; i < pCurHcb->HCS_MaxTar; i++) { pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE); } return (-1);}/***************************************************************************//* scsi reselection */int int_tul_resel(HCS * pCurHcb){ SCB *pCurScb; TCS *pCurTcb; BYTE tag, msg = 0; BYTE tar, lun; if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) { if (pCurScb->SCB_Status & SCB_SELECT) { /* if waiting for selection complete */ pCurScb->SCB_Status &= ~SCB_SELECT; } pCurHcb->HCS_ActScb = NULL; } /* --------- get target id---------------------- */ tar = TUL_RD(pCurHcb->HCS_Base, TUL_SBusId); /* ------ get LUN from Identify message----------- */ lun = TUL_RD(pCurHcb->HCS_Base, TUL_SIdent) & 0x0F; /* 07/22/98 from 0x1F -> 0x0F */ pCurTcb = &pCurHcb->HCS_Tcs[tar]; pCurHcb->HCS_ActTcs = pCurTcb; TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0); TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurTcb->TCS_JS_Period); /* ------------- tag queueing ? ------------------- */ if (pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG) { if ((tul_msgin_accept(pCurHcb)) == -1) return (-1); if (pCurHcb->HCS_Phase != MSG_IN) goto no_tag; TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1); TUL_W
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -