📄 scsi_1185.c
字号:
}#define GET_MIN_COUNT 127/* * SCSI message accept routine */sc_min(cs) register struct sc_chan_stat *cs;{ register struct scsi *sc; register struct scsi_stat *ss; register VOLATILE int dummy; sc = cs->sc; ss = &scsi_stat; sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE|Rb_RMSG; DMAC_WAIT0; if (min_flag == 1) flush_fifo(); dummy = sc_cmonr; DMAC_WAIT0; if ((dummy & R4_MREQ) == 0) { printf("sc_min: !REQ cmonr=%x\n", dummy); print_scsi_stat(); scsi_hardreset(); return; } retry_cmd_issue: int_stat2 &= ~R3_FNC; SET_CMD(SCMD_TR_INFO); do { do { dummy = sc_statr; DMAC_WAIT0; } while (dummy & R0_CIP); GET_INTR(&int_stat1, &int_stat2); /* clear interrupt */ } while ((int_stat2 & R3_FNC) == 0); int_stat2 &= ~R3_FNC; dummy = sc_ffstr; if (dummy & R5_FIE) { DMAC_WAIT; dummy = sc_ffstr; DMAC_WAIT0; if (dummy & R5_FIE) { dummy = sc_statr; DMAC_WAIT0; if ((dummy & R0_INIT) == 0) { /* * CXD1185 detect BSY false */ scsi_hardreset(); return; } } } dummy = sc_datr; /* get message byte */ DMAC_WAIT0; if (min_cnt[cs->chan_num] == 0) { sc->sc_message = sc->sc_identify; if (dummy == MSG_EXTND) { /* Extended Message */ min_cnt[cs->chan_num] = GET_MIN_COUNT; min_point[cs->chan_num] = sc->sc_param; bzero((caddr_t)sc->sc_param, 8); *min_point[cs->chan_num]++ = dummy; } else { switch ((dummy & MSG_IDENT)? MSG_IDENT : dummy) { case MSG_CCOMP: sc->sc_istatus |= INST_EP; break; case MSG_MREJ:#ifndef NOT_SUPPORT_SYNCTR if (mout_flag[cs->chan_num] == MOUT_SYNC_TR) sync_tr[cs->chan_num] = 0;#endif break; case MSG_IDENT: case MSG_RDP: ss->dma_stat = OFF; pad_start = 0; cs->comflg = OFF; /* * restore the saved value to Active pointers */ act_cmd_pointer = sc->sc_cdb.un_reserved; cs->act_trcnt = sc->sc_ctrnscnt; cs->act_point = sc->sc_cpoint; cs->act_tag = sc->sc_ctag; cs->act_offset = sc->sc_coffset; break; case MSG_SDP: /* * save Active pointers */ sc->sc_ctrnscnt = cs->act_trcnt; sc->sc_ctag = cs->act_tag; sc->sc_coffset = cs->act_offset; sc->sc_cpoint = cs->act_point; break; case MSG_DCNT: sc->sc_istatus |= INST_WR; ss->wrc++; break; default: sc->sc_message = MSG_MREJ; SET_CMD(SCMD_AST_ATN); printf("SCSI%d:sc_min() Unknown mes=0x%x, \n", cs->chan_num, dummy); } } } else { *min_point[cs->chan_num]++ = dummy; if (min_cnt[cs->chan_num] == GET_MIN_COUNT) min_cnt[cs->chan_num] = dummy; else min_cnt[cs->chan_num]--; if (min_cnt[cs->chan_num] <= 0) {#ifdef ABORT_SYNCTR_MES_FROM_TARGET if ((sc->sc_param[2] == 0x01) && (mout_flag[cs->chan_num] == MOUT_SYNC_TR)) {#else if (sc->sc_param[2] == 0x01) { /*}*/#endif register int i; /* * receive Synchronous transfer message reply * calculate transfer period val * tpm * 4/1000 us = 4/16 * (tpv + 1) */#define TPM2TPV(tpm) (((tpm)*16 + 999) / 1000 - 1)#ifndef NOT_SUPPORT_SYNCTR i = sc->sc_param[3]; /* get tpm */ i = TPM2TPV(i) << 4; if (sc->sc_param[4] == 0) sync_tr[cs->chan_num] = 0; else sync_tr[cs->chan_num] = i | sc->sc_param[4];#endif /* !NOT_SUPPORT_SYNCTR */ } else { sc->sc_message = MSG_MREJ; SET_CMD(SCMD_AST_ATN); /* assert ATN */ } } } SET_CMD(SCMD_NGT_ACK);}/* * SCSI message send routine */intsc_mout(cs) register struct sc_chan_stat *cs;{ register struct scsi *sc = cs->sc; register u_char *mp; register int cnt; register int iloop; register VOLATILE int dummy; VOLATILE int tmp; VOLATILE int tmp0; flush_fifo(); if (mout_flag[cs->chan_num] == 0) { mout_flag[cs->chan_num] = MOUT_IDENTIFY; if (sc->sc_message != 0) { sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE|Rb_RMSG; DMAC_WAIT0; if ((sc->sc_message == MSG_EXTND) && (sc->sc_param[2] == 0x01)) { cnt = 5; mp = sc->sc_param; sc->sc_param[3] = MIN_TP; if (sc->sc_param[4] > MAX_OFFSET_BYTES) sc->sc_param[4] = MAX_OFFSET_BYTES; mout_flag[cs->chan_num] = MOUT_SYNC_TR; } else { cnt = 1; mp = &sc->sc_message; } SET_CNT(cnt); SET_CMD(SCMD_TR_INFO|R0_TRBE); sc_datr = sc->sc_identify; DMAC_WAIT0; for (iloop = 1; iloop < cnt; iloop++) { sc_datr = *mp++; DMAC_WAIT; } do { dummy = sc_cmonr; DMAC_WAIT0; if ((dummy & R4_MBSY) == 0) return; dummy = sc_statr; DMAC_WAIT0; } while (dummy & R0_CIP); tmp = 0; GET_INTR(&tmp0, &tmp); /* clear interrupt */ if ((tmp & R3_FNC) == 0) { (void) WAIT_STATR_BITSET(R0_MIRQ); GET_INTR(&tmp0, &tmp); /* clear interrupt */ } do { dummy = sc_cmonr; DMAC_WAIT0; if ((dummy & R4_MBSY) == 0) return; } while ((dummy & R4_MREQ) == 0); SET_CMD(SCMD_NGT_ATN); (void) WAIT_STATR_BITCLR(R0_CIP); GET_INTR(&tmp0, &tmp); /* clear interrupt */ dummy = sc_cmonr; DMAC_WAIT0; if ((dummy & R4_MREQ) == 0) { printf("sc_mout: !REQ cmonr=%x\n", dummy); print_scsi_stat(); scsi_hardreset(); return; } SET_CMD(SCMD_TR_INFO); sc_datr = *mp++; DMAC_WAIT0; } else { dummy = sc_cmonr; DMAC_WAIT0; if (dummy & R4_MATN) { SET_CMD(SCMD_NGT_ATN); (void) WAIT_STATR_BITCLR(R0_CIP); GET_INTR(&tmp0, &tmp); /* clear interrupt */ } iloop = 0; do { dummy = sc_cmonr; DMAC_WAIT0; if (iloop++ > CHECK_LOOP_CNT) break; } while ((dummy & R4_MREQ) == 0); SET_CMD(SCMD_TR_INFO); sc_datr = sc->sc_identify; DMAC_WAIT0; } } else { dummy = sc_cmonr; DMAC_WAIT0; if (dummy & R4_MATN) { SET_CMD(SCMD_NGT_ATN); (void) WAIT_STATR_BITCLR(R0_CIP); GET_INTR(&tmp0, &tmp); /* clear interrupt */ } dummy = sc_cmonr; DMAC_WAIT0; if ((dummy & R4_MREQ) == 0) { printf("sc_mout: !REQ cmonr=%x\n", dummy); print_scsi_stat(); scsi_hardreset(); return; } SET_CMD(SCMD_TR_INFO); sc_datr = sc->sc_message; DMAC_WAIT0; }}/* * SCSI status accept routine */sc_sin(cs) register VOLATILE struct sc_chan_stat *cs;{ register VOLATILE int dummy; register int iloop; flush_fifo(); dummy = sc_cmonr; DMAC_WAIT0; if ((dummy & R4_MREQ) == 0) { printf("sc_sin: !REQ cmonr=%x\n", dummy); print_scsi_stat(); scsi_hardreset(); return; } sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE|Rb_RMSG; DMAC_WAIT0; SET_CMD(SCMD_TR_INFO); (void) WAIT_STATR_BITCLR(R0_CIP); int_stat2 &= ~R3_FNC; iloop = 0; do { if (iloop++ > CHECK_LOOP_CNT) break; GET_INTR(&int_stat1, &int_stat2); /* clear interrupt */ } while ((int_stat2 & R3_FNC) == 0); int_stat2 &= ~R3_FNC; cs->sc->sc_tstatus = sc_datr; /* get status byte */ DMAC_WAIT0;}/* * SCSI data in/out routine */sc_dio(cs) register VOLATILE struct sc_chan_stat *cs;{ register VOLATILE struct scsi *sc; register struct scsi_stat *ss; register int i; register int pages; register u_int tag; register u_int pfn; VOLATILE int phase; sc = cs->sc; ss = &scsi_stat; sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE; DMAC_WAIT0; if (cs->act_trcnt <= 0) { sc_dio_pad(cs); return; } switch (sc->sc_opcode) { case SCOP_READ: case SCOP_WRITE: case SCOP_EREAD: case SCOP_EWRITE: i = (cs->act_trcnt + sc->sc_bytesec -1) / sc->sc_bytesec; i *= sc->sc_bytesec; break; default: i = cs->act_trcnt; break; } SET_CNT(i); pad_cnt[cs->chan_num] = i - cs->act_trcnt; phase = sc_cmonr & SC_PMASK; DMAC_WAIT0; if (phase == DAT_IN) { if (sc_syncr == OFF) { DMAC_WAIT0; flush_fifo(); } }#if defined(mips) && defined(CPU_SINGLE) SET_CMD(SCMD_TR_INFO|R0_DMA|R0_TRBE);#endif#if defined(mips) && defined(CPU_SINGLE) dmac_gsel = CH_SCSI; dmac_ctrcl = (u_char)(cs->act_trcnt & 0xff); dmac_ctrcm = (u_char)((cs->act_trcnt >> 8) & 0xff); dmac_ctrch = (u_char)((cs->act_trcnt >> 16) & 0x0f); dmac_cofsh = (u_char)((cs->act_offset >> 8) & 0xf); dmac_cofsl = (u_char)(cs->act_offset & 0xff);#endif tag = 0; if (sc->sc_map && (sc->sc_map->mp_pages > 0)) { /* * Set DMAC map entry from map table */ pages = sc->sc_map->mp_pages; for (i = cs->act_tag; i < pages; i++) { if ((pfn = sc->sc_map->mp_addr[i]) == 0) panic("SCSI:sc_dma() zero entry");#if defined(mips) && defined(CPU_SINGLE) dmac_gsel = CH_SCSI; dmac_ctag = (u_char)tag++; dmac_cmap = (u_short)pfn;#endif }#ifdef MAP_OVER_ACCESS# if defined(mips) && defined(CPU_SINGLE) dmac_gsel = CH_SCSI; dmac_ctag = (u_char)tag++; dmac_cmap = (u_short)pfn;# endif#endif } else { /* * Set DMAC map entry from logical address */ pfn = (u_int)vtophys(cs->act_point) >> PGSHIFT; pages = (cs->act_trcnt >> PGSHIFT) + 2; for (i = 0; i < pages; i++) {#if defined(mips) && defined(CPU_SINGLE) dmac_gsel = CH_SCSI; dmac_ctag = (u_char)tag++; dmac_cmap = (u_short)pfn + i;#endif } }#if defined(mips) && defined(CPU_SINGLE) dmac_gsel = CH_SCSI; dmac_ctag = 0;#endif if (phase == DAT_IN) { ss->dma_stat = SC_DMAC_RD;#if defined(mips) && defined(CPU_SINGLE) /* * auto pad flag is always on */ dmac_gsel = CH_SCSI; dmac_cctl = DM_MODE|DM_APAD; DMAC_WAIT; dmac_cctl = DM_MODE|DM_APAD|DM_ENABLE; DMAC_WAIT0;#endif } else if (phase == DAT_OUT) { ss->dma_stat = SC_DMAC_WR;#if defined(mips) && defined(CPU_SINGLE) dmac_gsel = CH_SCSI; dmac_cctl = DM_APAD; DMAC_WAIT; dmac_cctl = DM_APAD|DM_ENABLE; DMAC_WAIT0;#endif /* DMAC start on mem->I/O */ }}#define MAX_TR_CNT24 ((1 << 24) -1)sc_dio_pad(cs) register VOLATILE struct sc_chan_stat *cs;{ register VOLATILE int phase; register int dummy; if (cs->act_trcnt >= 0) return; pad_start = 1; SET_CNT(MAX_TR_CNT24); SET_CMD(SCMD_TR_PAD|R0_TRBE); dummy = sc_cmonr & SC_PMASK; DMAC_WAIT0; if (dummy == DAT_IN) dummy = sc_datr; /* get data */ else sc_datr = 0; /* send data */}print_scsi_stat(){ register struct scsi_stat *ss; register VOLATILE int i; int dummy; ss = &scsi_stat; printf("ipc=%d wrc=%d wbc=%d\n", ss->ipc, ss->wrc, ss->wbc);}/* * return 0 if it was done. Or retun TRUE if it is busy. */sc_busy(chan) register int chan;{ return ((int)chan_stat[chan].sc);}/* * append channel into Waiting Bus_free queue */append_wb(cs) register VOLATILE struct sc_chan_stat *cs;{ register int s; s = splclock(); /* inhibit process switch */ if (wbq_actf == NULL) wbq_actf = cs; else wbq_actl->wb_next = cs; wbq_actl = cs; cs->sc->sc_istatus = INST_WAIT; scsi_stat.wbc++; splx(s);}/* * get channel from Waiting Bus_free queue */get_wb_chan(){ register int s; register int chan; s = splclock(); /* inhibit process switch */ if (wbq_actf == NULL) { chan = -1; } else { chan = wbq_actf->chan_num; if ((chan < 0) || (chan >= NTARGET) || (chan == SC_OWNID)) chan = -1; } splx(s); return (chan);}/* * release channel from Waiting Bus_free queue */release_wb(){ register VOLATILE struct sc_chan_stat *cs; register int s; int error; s = splclock(); /* inhibit process switch */ error = 0; if (wbq_actf == NULL) { error = -1; } else { cs = wbq_actf; wbq_actf = cs->wb_next; cs->wb_next = NULL; if (wbq_actl == cs) wbq_actl = NULL; cs->sc->sc_istatus &= ~INST_WAIT; scsi_stat.wbc--; } splx(s); return (error);}adjust_transfer(cs) register struct sc_chan_stat *cs;{ register struct scsi *sc; register struct scsi_stat *ss; register VOLATILE u_int remain_cnt; register u_int offset; u_int sent_byte; sc = cs->sc; ss = &scsi_stat; if (pad_start) { pad_start = 0; remain_cnt = 0; } else {# if defined(mips) && defined(CPU_SINGLE) remain_cnt = GET_CNT(); remain_cnt -= pad_cnt[cs->chan_num]; if (ss->dma_stat == SC_DMAC_WR) { /* * adjust counter in the FIFO */ remain_cnt += sc_ffstr & R5_FIFOREM; }# endif } sent_byte = sc->sc_ctrnscnt - remain_cnt; cs->act_trcnt = remain_cnt; offset = sc->sc_coffset + sent_byte; cs->act_tag += (offset >> PGSHIFT); cs->act_offset = offset & PGOFSET; if ((sc->sc_map == NULL) || (sc->sc_map->mp_pages <= 0)) cs->act_point += sent_byte;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -