📄 sm.c
字号:
if (s & DVMA_REQPEND) { /* DMA request pending */ EPRINTF1("sm_intr: DVMA-scsi req_pend, stat= %x\n", s); /* DMA request pending, should not ocurred */ toutcnt = LOOP_4SEC; /* must be over 2sec */ /* wait for a short while to see it will clear itself */ while ((--toutcnt) && (dvma->ctl_stat & DVMA_REQPEND)); if (toutcnt == ZERO) { smsnap->cur_err = SE_REQPEND; goto INTR_CHK_ERR; } } if (s & DVMA_ERRPEND) { /* memory exception error */ smsnap->cur_err = SE_MEMERR; DPRINTF1("sm_intr: DVMA mem_err, stat= %x\n", s); goto INTR_CHK_ERR; } } /* status errors are mainly for internal firmware debug */ if (espstat & STAT_ERR_MASK) { smsnap->cur_retry++; /* ESP's status reg ERROR */ if (espstat & ESP_STAT_PERR) { /* parity error */ EPRINTF("sm_intr: SCSI bus parity error\n"); smsnap->cur_err = SE_PARITY; } /* if mismatch, the 'DMA" direction is wrong */ if ((((dvma->ctl_stat & DVMA_WRITE) == ZERO) && (smsnap->sync_chk == SM_RECV_DATA)) || ((dvma->ctl_stat & DVMA_WRITE) && (smsnap->sync_chk == SM_SEND_DATA))) { EPRINTF2("sm_intr: wrong dma dir= %x, stat= %x\n", smsnap->sync_chk, dvma->ctl_stat); smsnap->cur_err = SE_DIRERR; } if ((ESP_RD.fifo_flag & KEEP_5BITS) == MAX_FIFO_FLAG) { /* fifo overwritten */ EPRINTF1("sm_intr: fifo_flag ERROR= %x\n", ESP_RD.fifo_flag); /* the 'TOP of FIFO' had been overwritten */ smsnap->cur_err = SE_FIFOVER; }#ifdef notdef /* If none of the above, GROSS error is from cmd overflown */ /* top_of_cmd had been overwritten */ /* ignore this for P4-ESP for timing reason */ if (smsnap->cur_err == ZERO) { EPRINTF1("sm_intr: cur_cmd= %x\n", ESP_RD.cmd); smsnap->cur_err = SE_CMDOVER; }#endif notdef if (smsnap->cur_err) { EPRINTF1("sm_intr: esp stat_err= %x\n", espstat); goto INTR_CHK_ERR; } } } INTR_CHK_STAT: /* CORRECTON for an ESP ERRATA: ensure phase change detection reset */ ESP_WR.cmd = CMD_NOP; smsnap->esp_stat &= ESP_PHASE_MASK; s = ESP_RD.stat; i = s & ESP_PHASE_MASK; if (i != smsnap->esp_stat) { DPRINTF2("sm_intr: phase changed, old= %x, new= %x\n", smsnap->esp_stat, i); smsnap->esp_stat = i; espstat = s; i = ESP_RD.intr; if (i) { DPRINTF2("sm_intr: INTR changed, old= %x, new= %x\n", smsnap->esp_intr, i); smsnap->esp_intr = i; } } DPRINTF2("sm_intr: ESP_int= %x, state= %x\n", smsnap->esp_intr, smsnap->cur_state); switch (smsnap->esp_intr) { case ESP_INT_DISCON: /* disconnect INT */ switch (smsnap->cur_state) { /* case STATE_MSG_DISCON not needed */ case STATE_COMP_REQ: /* cmd completed seuqence sent out */ case STATE_MSG_CMPT: /* command completed msg accepted */ /* All ZERO= good, All other, bit 1= check cond, */ /* bit 3= busy, bit 4=resev conflict are errors */ if (smsnap->scsi_status & SCSI_BUSY_MASK) { DPRINTF1("sm_intr: BUS_ERR status= %x\n", smsnap->scsi_status); smsnap->cur_err = SE_BUSTATERR; } smsnap->cur_state = STATE_FREE; break; case STATE_SEL_REQ: /* selection command timeout */ smsnap->cur_err = SE_SELTOUT; case STATE_FREE: break; default: /* could be from target dropping BSY */ EPRINTF("sm_intr: target drop busy\n"); smsnap->cur_err = SE_PHASERR; } break; case ESP_INT_FCMP:/* function complete INT */ case ESP_INT_BUS: /* from"select_seq","comp_seq","msg_accept" cmd */ case INT_OK_MASK: /* from"select_seq","comp_seq","msg_accept" cmd */ if (smsnap->cur_state == STATE_SEL_REQ) { /* for initator, only SEL_SEQ has */ /* intermittent step indications: */ /* both sel w/wo ATN need 4 steps to complete OK */ /* only sel w/ATN/stop is 3 steps to complete OK */ /* both sel w/wo ATN need 4 steps to complete OK */ if ((smsnap->esp_step & KEEP_3BITS) != STEP_SEL_OK) { EPRINTF2("sm_intr: BAD_SEL, step= %x, stat= %x\n", smsnap->esp_step, smsnap->esp_stat); if (smsnap->esp_stat != ESP_PHASE_STATUS) { smsnap->cur_err = SE_SELTOUT; goto INTR_CHK_ERR; } ESP_WR.cmd = CMD_FLUSH; ESP_WR.cmd = CMD_NOP; /* ready for next phase */ } smsnap->cur_state = STATE_SEL_DONE; } switch (smsnap->esp_stat) { /* current phase */ case ESP_PHASE_DATA_IN: /* either data in or out */ case ESP_PHASE_DATA_OUT: /* either data in or out */ DPRINTF1("sm_intr: data phase, pre_state= %x\n", smsnap->cur_state); DEBUG_DELAY(1000000); /* if this phase came after a non-command phase */ /* try to service this unexpected data phase */ if (smsnap->cur_state != STATE_SEL_DONE) { DPRINTF("sm_intr: wrong data phase\n"); if (++smsnap->cur_retry > MAX_RETRY) { EPRINTF("sm_intr: wrong data phase\n"); smsnap->cur_err = SE_PHASERR; goto INTR_CHK_ERR; } ESP_WR.cmd = CMD_NOP; smsnap->esp_stat = ESP_RD.stat & ESP_PHASE_MASK; i = ESP_RD.intr; DPRINTF2("sm_intr: stat= %x, intr = %x\n", smsnap->esp_stat, i); if (i) { smsnap->esp_intr = i; goto INTR_CHK_STAT; } else /* just service and ignore */ goto INTR_RTN; } /* assume ALL cmd that has NO data, do not need DMA */ if (smsnap->sync_chk == SM_NO_DATA) { DPRINTF1("sm_intr: spurious data phase, state= %x\n", smsnap->cur_state); if (++smsnap->cur_retry > MAX_RETRY) { EPRINTF1("sm_intr: spurious data phase, state= %x\n", smsnap->cur_state); smsnap->cur_err = SE_PHASERR; goto INTR_CHK_ERR; } /* try to fake one out a data xfr */ ESP_WR.cmd = CMD_TRAN_PAD | CMD_DMA; } else { /* data transfer required */ smsnap->cur_state = STATE_DATA_REQ; /* force async transfer */ ESP_WR.sync_offset = ZERO; /* enable dvma and R/W*/ sm_dma_setup(h_sip); /* add in per ESP errata note */ ESP_WR.cmd = CMD_NOP; ESP_WR.cmd = CMD_TRAN_INFO | CMD_DMA; } break; case ESP_PHASE_STATUS: DPRINTF1("sm_intr: status phase, pre_state= %x\n", smsnap->cur_state); if (sm_dma_cleanup(h_sip, espstat)) goto INTR_CHK_ERR; smsnap->cur_state = STATE_COMP_REQ; DPRINTF("sm_intr: send complete_seq\n"); ESP_WR.cmd = CMD_COMP_SEQ; break; case ESP_PHASE_MSG_IN: DPRINTF2("sm_intr: msg_in phase, state= %x, flag= %x\n", smsnap->cur_state, ESP_RD.fifo_flag); switch (smsnap->cur_state) { case STATE_COMP_REQ: /* two bytes */ smsnap->scsi_status = ESP_RD.fifo_data; case STATE_MSGIN_REQ: smsnap->scsi_message = ESP_RD.fifo_data; break; case STATE_DATA_REQ: DPRINTF2("sm_intr: msg_in dma_stat= %x, cnt= %x\n", dvma->ctl_stat, h_sip->cc); if (sm_dma_cleanup(h_sip, espstat)) goto INTR_CHK_ERR; /* fall through */ default: /* get message byte */ if (ESP_RD.fifo_flag) { if (ESP_RD.fifo_flag > 1) { EPRINTF2("sm_intr: msg_in flag= %x, state= %x\n", ESP_RD.fifo_flag, smsnap->cur_state); EPRINTF2("sm_intr: stat= %x, intr= %x\n", smsnap->esp_stat, smsnap->esp_intr); while (ESP_RD.fifo_flag) { i = ESP_RD.fifo_data; EPRINTF1(" %x", i); } ESP_WR.cmd = CMD_NOP; goto INTR_CHK_STAT; } smsnap->scsi_message = ESP_RD.fifo_data; } else { ESP_WR.cmd = CMD_TRAN_INFO; smsnap->cur_state = STATE_MSGIN_REQ; goto INTR_RTN; } } DPRINTF2("sm_intr: status= %x, message= %x\n", smsnap->scsi_status, smsnap->scsi_message); DPRINTF1("sm_intr: flag= %x\n", ESP_RD.fifo_flag); switch (smsnap->scsi_message) { case SC_COMMAND_COMPLETE: case SC_NO_OP: smsnap->cur_state = STATE_MSG_CMPT; /* save the scsi_status for now */ /* a disconnect INT shuold show up */ /* after sending out "msg_accpt" cmd */ /* at that time, we are TOTALLY done */ break; case SC_PARITY: DPRINTF("sm_intr: PARITY_err msg\n"); smsnap->cur_err = SE_PARITY; smsnap->cur_state = STATE_MSG_PARITY; break; case SC_DEVICE_RESET: DPRINTF("sm_intr: RESET_err msg\n"); smsnap->cur_state = STATE_RESET; smsnap->cur_err = SE_RESET; break; case SC_ABORT: DPRINTF("sm_intr: ABORT_err msg\n"); smsnap->cur_state = STATE_MSG_ABORT; smsnap->cur_err = SE_MSGERR; break; /* no need to send abort msg */ case SC_MSG_REJECT: DPRINTF("sm_intr: REJECT_err msg\n"); smsnap->cur_state = STATE_MSG_REJECT; break; /* All other is ocnsidered ERROR for now */ case SC_DISCONNECT: case SC_SAVE_DATA_PTR: case SC_RESTORE_PTRS: case SC_EXTENDED_MESSAGE: case SC_LINK_CMD_CPLT: case SC_FLAG_LINK_CMD_CPLT: case SC_IDENTIFY: case SC_DR_IDENTIFY: default: EPRINTF1("sm_intr: unsupported message: %x\n", smsnap->scsi_message); smsnap->cur_err = SE_MSGERR; } /* send a message accpt cmd */ ESP_WR.cmd = CMD_MSG_ACPT; ESP_WR.cmd = CMD_NOP; /* for ESP bug */ break; case ESP_PHASE_MSG_OUT: case ESP_PHASE_COMMAND: default: /* all others are bad, just set PHASE error */ EPRINTF1("sm_intr: bad phase, pre_state: %x\n", smsnap->cur_state); smsnap->cur_err = SE_PHASERR; } break; case ESP_INT_RESET: /* external scsi RESET interrupt received */ DPRINTF1("sm_intr: SCSI bus_reset int, state= %x\n", smsnap->cur_state); /* just set flag, and sm_reset() will be called later */ smsnap->cur_err = SE_RESET; break; case ESP_INT_ILLCMD: /* illegal cmd */ case INT_ILL_BUS: /* illegal bus status */ DPRINTF1("sm_intr: illegal cmd= %x\n", ESP_RD.cmd); smsnap->cur_err = SE_ILLCMD; break; case ESP_INT_RESEL: case ESP_INT_SELATN: /* selected with ATN -- target cmd */ case ESP_INT_SEL: /* selected without ATN -- target cmd */ default: /* all others are not supported NOW */ EPRINTF1("sm_intr: bad interrupt= %x\n", smsnap->esp_intr); smsnap->cur_err = SE_PHASERR; }INTR_CHK_ERR: if (smsnap->cur_retry > MAX_RETRY) { EPRINTF1("sm_intr: retry exhausted, phase= %x\n", smsnap->cur_state); DEBUG_DELAY(10000000); smsnap->cur_err = SE_TOUTERR; } /* Just simply pass the status to upper level callers */ if (smsnap->cur_err) {#ifdef SMDEBUG if (smsnap->cur_err != SE_BUSTATERR) { EPRINTF2("sm_intr: ESP_ERR= %x, phase= %x\n", smsnap->cur_err, smsnap->cur_state); }#endif SMDEBUG DEBUG_DELAY(1000000); switch (smsnap->cur_err) { case SE_SELTOUT: /* select/resel timeout */ ESP_WR.cmd = CMD_FLUSH; ESP_WR.cmd = CMD_NOP; break; /* return error, but NO reset */ case SE_BUSTATERR: /* bus ERR, i.e, chk_cond, busy */ smsnap->cur_err = ZERO; smsnap->cur_state = STATE_FREE; break; /* return error, but NO reset */ case SE_MEMERR: /* memory exception error during DMA */ case SE_DIRERR: /* WRONG DMA direction, could trash MEM */ case SE_DVMAERR: /* DVMA Drain stuck */ case SE_ILLCMD: /* illegal command detected */ case SE_PARITY: /* either ESP or target parity ERR */ case SE_FIFOVER: /* ESP status err, fifo overflown */ case SE_CMDOVER: /* ESP status err, command overflown */ case SE_RESET: /* reset detected */ /* software reset (NO external SCSI reset) */ sm_reset(h_sip, RESET_INT_ONLY); break; case SE_TOUTERR: /* DMA timed out */ case SE_MSGERR: /* ESP has un-expected message */ case SE_PHASERR: /* ESP has un-expected phase */ /* possible HW error, do a HARD-SCSI reset */ sm_reset(h_sip, RESET_ALL_SCSI); break; case SE_REQPEND: /* DMA's request pending stuck */ toutcnt = (int)dvma->ctl_stat; EPRINTF1("sm_intr: DVMA-scsi req_pend stuck, stat= %x\n", toutcnt); break; case SE_SPURINT: EPRINTF1("sm_intr: spurious esp_intr= %x\n", smsnap->esp_intr); smsnap->cur_err = ZERO; goto INTR_RTN; default: DPRINTF1("sm_intr: spurious esp_err= %x\n", smsnap->cur_err); } smsnap->cur_state = STATE_FREE; }INTR_RTN: DPRINTF1("sm_intr: INTR_END, state= %x\n", smsnap->cur_state); DEBUG_DELAY(100000);}#endif (defined sun4) || (defined sun3x)/* end of SCSI-ESP standalone boot driver (smboot.c) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -