📄 ini910u.c
字号:
char mod_ALTPD(hcsp, tcsp)
register HCS *hcsp;
register TCS *tcsp;
{
TUL_WR(hcsp->Base + TUL_SConfig, tcsp->sConfig);
return 1;
}
/**************** tulip_scsi rtn *************************************/
char tulip_scsi(hcsp)
register HCS *hcsp;
{
register TULSCB *scbp;
register TCS *tcsp;
UBYTE readByte;
int rtn;
hcsp->JSStatus0 = TUL_RD(hcsp->Base, TUL_SStatus0);
if (hcsp->JSStatus0 & TSS_INT_PENDING) {
if (hcsp->JSInt = (TUL_RD(hcsp->Base, TUL_SInt)) ) {
hcsp->Phase = hcsp->JSStatus0 & TSS_PH_MASK;
hcsp->JSStatus1 = TUL_RD(hcsp->Base, TUL_SStatus1);
if (hcsp->JSInt & TSS_SCSIRST_INT) {
/* if SCSI bus reset detected */
int_scsi_rst(hcsp);
return 0;
}
/* Happens when msg_accept SCSI cmd 0xF find out bus free */
if (hcsp->JSInt & TSS_DISC_INT) {
return 0;
}
if (hcsp->JSInt & TSS_RESEL_INT) {
/* if selected/reselected interrupt */
int_resel(hcsp);
return 0;
}
if (hcsp->JSInt & TSS_SEL_TIMEOUT) {
/* if selected/reselected timeout interrupt */
int_busfree(hcsp);
return 0;
}
if (hcsp->JSInt & (TSS_FUNC_COMP | TSS_BUS_SERV)) {
if ( (scbp = hcsp->ActScb) != 0) {
next_state(hcsp, scbp);
}
return 1;
}
/* if selected or scam selected*/
TUL_WR( hcsp->Base + TUL_SSignal, 0);
}
}
if (hcsp->ActScb != 0) {
return 1;
}
if ( (scbp = hcsp->FirstPend) == NULL) {
return 1;
}
tcsp = &hcsp->Tcs[scbp->Target];
/* program HBA's SCSI ID & target SCSI ID */
TUL_WR( hcsp->Base + TUL_SScsiId,
(hcsp->HaId << 4) | (scbp->Target & 0x0F) );
if (scbp->Opcode == ExecSCSI) {
mod_ALTPD(hcsp, tcsp);
TUL_WR(hcsp->Base + TUL_SPeriodOffset, tcsp->JS_PeriodOffset);
if ( (tcsp->Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {
/* do wdtr negotiation */
select_atn_stop(hcsp, scbp);
} else if ( (tcsp->Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {
/* do sync negotiation */
select_atn_stop(hcsp, scbp);
} else {
if (scbp->TagMsg) {
select_atn3(hcsp, scbp);
} else {
select_atn(hcsp, scbp);
}
}
if (scbp->Flags & SCF_POLL) {
while (wait_tulip(hcsp) != -1) {
if ( next_state(hcsp, scbp) == -1)
break;
}
}
} else if (scbp->Opcode == BusDevRst) {
select_atn_stop(hcsp, scbp);
scbp->NxtStat = 8;
if (scbp->Flags & SCF_POLL) {
while (wait_tulip(hcsp) != -1) {
if (next_state(hcsp, scbp) == -1)
break;
}
}
} else if (scbp->Opcode == AbortCmd ) {
select_atn_stop(hcsp, scbp);
if (scbp->Flags & SCF_POLL) {
while (wait_tulip(hcsp) != -1) {
if (next_state(hcsp, scbp) == -1)
break;
}
}
} else {
ll_pop_pend_scb(hcsp);
scbp->Status = TULSCB_DONE; /* done */
scbp->HaStat = 0x16; /* bad command */
ll_append_done_scb(hcsp, scbp);
}
return 0;
}
/***************** next_state rtn *****************************/
char next_state(hcsp, scbp)
register HCS *hcsp;
register TULSCB *scbp;
{
UCHAR xfrPeriod[8] = { /* fast 20 */
/* nanosecond devide by 4 */
12, /* 50ns, 20M */
18, /* 75ns, 13.3M */
25, /* 100ns, 10M */
31, /* 125ns, 8M */
37, /* 150ns, 6.6M */
43, /* 175ns, 5.7M */
50, /* 200ns, 5M */
62 /* 250ns, 4M */
};
TCS * tcsp;
UBYTE tar;
ULONG_PTR TulSCmd, TulSFifo;
long i, cnt, xcnt, fifoCnt;
char phase;
UCHAR sta, ctrl;
UCHAR readByte;
TULSCB * pTmpScb;
tcsp = hcsp->ActTcs;
TulSCmd = hcsp->Base + TUL_SCmd;
TulSFifo = hcsp->Base + TUL_SFifo;
switch (scbp->NxtStat) {
case 1:
if (scbp != ll_pop_pend_scb(hcsp)) {
TulPanic("case1: scbp != ll_pop_pend_scb(hcsp)\n");
}
scbp->Status = TULSCB_BUSY;
ll_append_busy_scb(hcsp, scbp);
if (hcsp->Phase == MSG_OUT) {
if (scbp->Opcode == AbortCmd) {
if (scbp->TagMsg == 0) {
msgout_abort(hcsp);
} else
{
msgout_abort_tag(hcsp);
}
return 3;
} else
{
/* enable BUS */
TUL_WR(hcsp->Base + TUL_SCtrl1, TSC_EN_BUS_IN);
/* send out identify message */
TUL_WR(hcsp->Base + TUL_SFifo, scbp->Ident);
if (scbp->TagMsg != 0) {
TUL_WR(TulSFifo, scbp->TagMsg);
TUL_WR(TulSFifo, scbp->TagId);
}
if ((tcsp->Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {
tcsp->Flags |= TCF_WDTR_DONE;
TUL_WR(TulSFifo, MSG_EXTEND);
TUL_WR(TulSFifo, 2); /* extended msg length */
TUL_WR(TulSFifo, 3); /* sync request */
TUL_WR(TulSFifo, 1); /* start from 16bit xfer */
} else
{
if ((tcsp->Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0 ) {
tcsp->Flags |= TCF_SYNC_DONE;
TUL_WR(TulSFifo, MSG_EXTEND);
TUL_WR(TulSFifo, 3); /* extended msg length */
TUL_WR(TulSFifo, 1); /* sync request */
TUL_WR(TulSFifo, xfrPeriod[tcsp->xfrPeriodIdx]);
TUL_WR(TulSFifo, MAX_OFFSET); /* REQ/ACK offset */
}
}
TUL_WR(TulSCmd, TSC_XF_FIFO_OUT);
if (wait_tulip(hcsp) == -1)
return - 1;
TUL_WR(hcsp->Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
readByte = TUL_RD(hcsp->Base, TUL_SSignal);
TUL_WR( hcsp->Base + TUL_SSignal, readByte & 0x47);
goto state_3;
}
} else
{
/* not MSG_OUT phase, ATN on */
TUL_WR( hcsp->Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
readByte = TUL_RD(hcsp->Base, TUL_SSignal);
TUL_WR( hcsp->Base + TUL_SSignal, readByte & 0x47);
goto state_3;
}
break;
case 2:
if (scbp != ll_pop_pend_scb(hcsp)) {
TulPanic("case2: scbp != ll_pop_pend_scb(hcsp)\n");
}
scbp->Status = TULSCB_BUSY;
ll_append_busy_scb(hcsp, scbp);
hcsp->JSStatus1 = TUL_RD( hcsp->Base, TUL_SStatus1);
if (hcsp->JSStatus1 & TSS_CMD_PH_CMP) {
goto state_4;
}
TUL_WR(hcsp->Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
readByte = TUL_RD(hcsp->Base, TUL_SSignal);
TUL_WR( hcsp->Base + TUL_SSignal, readByte & 0x47);
goto state_3;
case 3:
state_3:
phase = hcsp->Phase;
for (; ; ) {
switch (phase) {
case CMD_OUT: /* Command phase */
for ( i = 0; i < (int)scbp->CDBLen; i++) {
TUL_WR( TulSFifo, scbp->CDB[i]);
}
TUL_WR(TulSCmd, TSC_XF_FIFO_OUT);
if ((phase = wait_tulip(hcsp)) == -1)
return phase;
if (phase == CMD_OUT) {
return bad_seq(hcsp);
}
goto state_4;
case MSG_IN: /* Message in phase */
scbp->NxtStat = 0x3;
if ((phase = msgin(hcsp, scbp)) == -1)
return - 1;
break;
case STATUS: /* Status phase */
if ((phase = status_msg(hcsp, scbp)) == -1) {
return - 1;
}
break;
case MSG_OUT: /* Message out phase */
if ((tcsp->Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0 ) {
tcsp->Flags |= TCF_SYNC_DONE;
TUL_WR(TulSFifo, MSG_EXTEND);
TUL_WR(TulSFifo, 3); /* extended msg length */
TUL_WR(TulSFifo, 1); /* sync request */
TUL_WR(TulSFifo, xfrPeriod[tcsp->xfrPeriodIdx]);
TUL_WR(TulSFifo, MAX_OFFSET); /* REQ/ACK offset */
TUL_WR(TulSCmd, TSC_XF_FIFO_OUT);
if ((phase = wait_tulip(hcsp)) == -1)
return - 1;
TUL_WR(hcsp->Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
readByte = TUL_RD(hcsp->Base, TUL_SSignal);
TUL_WR( hcsp->Base + TUL_SSignal, readByte & 0x47);
} else {
if ((phase = msgout_nop(hcsp)) == -1)
return - 1;
}
break;
default:
return bad_seq(hcsp);
}
} /* for */
case 4:
state_4:
if ((scbp->Flags & SCF_DIR) == SCF_NO_XF) {
goto state_6;
}
phase = hcsp->Phase;
for (; ; ) {
if (scbp->BufLen == 0) {
goto state_6;
}
switch (phase) {
case DATA_IN: /* Data in phase */
return xfer_data_in(hcsp, scbp);
case DATA_OUT: /* Data out phase */
return xfer_data_out(hcsp, scbp);
case MSG_IN: /* Message in phase */
scbp->NxtStat = 0x4;
if ((phase = msgin(hcsp, scbp)) == -1)
return phase;
break;
case STATUS: /* Status phase */
if ((phase = status_msg(hcsp, scbp)) == -1) {
if ( (!(scbp->Mode & SCM_RSENS)) &&
(!(scbp->TaStat == TARGET_BUSY)) ) {
/* not in auto req sense modeand target not busy*/
if (scbp->Srb->DataTransferLength -= scbp->BufLen)
if ((scbp->Flags & SCF_DIR) != SCF_NO_DCHK)
scbp->HaStat = HOST_DO_DU; /* 10/21/97 */
}
return phase;
}
break;
case MSG_OUT: /* Message out phase */
if ( hcsp->JSStatus0 & TSS_PAR_ERROR ) {
scbp->BufLen = 0;
scbp->HaStat = HOST_DO_DU;
if ((phase = msgout_ide(hcsp)) == -1)
return phase;
goto state_6;
} else
{
if ((phase = msgout_nop(hcsp)) == -1)
return phase;
}
break;
default:
return bad_seq(hcsp);
}
}
case 5:
cnt = TUL_RDLONG(hcsp->Base, TUL_SCnt0) & 0xffffff;
/************** DMA direction == DATA_IN **************************/
if (TUL_RD(hcsp->Base, TUL_XCmd) & 0x20) { /* check direction */
if ( hcsp->JSStatus0 & TSS_PAR_ERROR ) {
scbp->HaStat = HOST_DO_DU;
}
/*data underrun: when mode
sense cmd (0x1A) request 192 byte, but target drive xfer
146 byte then change phase to STATUS, in this case, we need
to clean up the DMA xfer */
sta = TUL_RD(hcsp->Base, TUL_XStatus);
if ((sta & XPEND)) { /* DMA xfer pending */
/* force DMA xfer the left over bytes */
ctrl = TUL_RD(hcsp->Base, TUL_XCtrl);
TUL_WR(hcsp->Base + TUL_XCtrl, ctrl | 0x80 ); /* set bit 7 */
/* wait until DMA xfer not pending */
while ( (sta = TUL_RD(hcsp->Base, TUL_XStatus)) & XPEND ) {
}
TUL_WR(hcsp->Base + TUL_XCtrl, ctrl); /* clear bit 7*/
} /* if (sta & XPEND) : DMA xfer pending */
} else
{
/************** DMA direction == DATA OUT *******************/
if (!(TUL_RD(hcsp->Base, TUL_SStatus1) & TSS_XFER_CMP)) {
fifoCnt = TUL_RD(hcsp->Base, TUL_SFifoCnt) & 0x1f;
if (tcsp->JS_PeriodOffset & TSC_WIDE_SCSI)
fifoCnt = fifoCnt << 1;
cnt += fifoCnt;
TUL_WR(hcsp->Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
}
/* st5_xfer_done: */
/* if DMA xfer is pending, abort DMA xfer */
if (TUL_RD(hcsp->Base, TUL_XStatus) & XPEND) {
ULONG countdown = 500;
/* ----------- ABORT ----------------------*/
/* TUL_WR(hcsp->Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO);*/
TUL_WR(hcsp->Base + TUL_XCmd, TAX_X_ABT); /* 02/26/98 */
/* wait Abort DMA xfer done */
while (((TUL_RD(hcsp->Base, TUL_Int) & XABT) == 0) &&
(countdown != 0)) {
ScsiPortStallExecution(1);
countdown--;
}
if(countdown == 0) {
DebugPrint((0, "initio::nextstate - XABT bit was never set\n"));
}
}
} /* DMA direction == DATA_OUT */
xcnt = scbp->BufLen - cnt;
scbp->BufLen = cnt;/* left byte cnt to be xfer */
if (scbp->BufLen == 0) {
goto state_6;
}
if (scbp->Flags & SCF_SG) {
register SG *sgp;
ULONG i;
sgp = &scbp->SGList[scbp->SGIdx];
for (i = scbp->SGIdx; i < scbp->SGMax; sgp++, i++) {
xcnt -= sgp->Len;
if (xcnt < 0) {
xcnt += sgp->Len;
sgp->Ptr += (ULONG)xcnt;
sgp->Len -= (ULONG)xcnt;
scbp->BufPtr += ((ULONG)(i - scbp->SGIdx) << 3);
scbp->SGLen = (UBYTE)(scbp->SGMax - i);
scbp->SGIdx = (UWORD)i;
goto state_4;
}
} /* for */
goto state_6;
} else
{
scbp->BufPtr += xcnt;
}
goto state_4;
case 6:
state_6:
phase = hcsp->Phase;
for (; ; ) {
switch (phase) {
case MSG_IN:
scbp->NxtStat = 0x6;
if ((phase = msgin(hcsp, scbp)) == -1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -