📄 i91uscsi.c
字号:
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;#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);#endif tulip_main(pCurHcb);#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);#endif pCurHcb->HCS_Semaph = 1; TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F); }#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);#else restore_flags(flags);#endif 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 */ } /* 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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -