📄 scsi_1185.c
字号:
sel_stat[ss->ipc] = SEL_RSLD; ss->ipc = -1; int_stat1 |= R2_RSL; } if (int_stat1 & R2_RSL) { /* * Reselection */ sc_resel(); int_stat1 &= ~R2_RSL; if (sel_stat[ss->ipc] == SEL_RSL_WAIT) goto scintr_exit; } if ((ss->ipc >= 0) && (ss->ipc != SC_OWNID) && (sel_stat[ss->ipc] == SEL_SUCCESS)) { if (int_stat2 & R3_PHC) { /* * Phase change */ int_stat2 &= ~(R3_PHC|R3_RMSG); sc_pmatch(); } else if (int_stat2 & R3_RMSG) { /* * message Phase */ if (min_flag > 0) { int_stat2 &= ~(R3_PHC|R3_RMSG); sc_pmatch(); } } else if (ss->dma_stat != OFF) { dummy = sc_cmonr; DMAC_WAIT0; if ((dummy & (R4_MMSG|R4_MCD|R4_MREQ)) == R4_MREQ) { /* * still DATA transfer phase */ sc_dio_pad(ss->ip); } } else if (ss->ip->comflg == CF_SEND) { dummy = sc_cmonr; DMAC_WAIT0; if ((dummy & SC_PMASK) == COM_OUT) { /* * command out phase */ sc_cout(ss->ip); } } } else { if (int_stat2 & (R3_PHC|R3_RMSG)) goto scintr_exit; } if ((int_stat1 & (R2_STO|R2_RSL|R2_ARBF)) || (int_stat2 & (R3_DCNT|R3_SRST|R3_PHC|R3_SPE))) { /* * still remain intrq */ goto scintr_loop; }scintr_exit: return (1);}/* * SCSI bus reset routine * scsi_hardreset() is occered a reset interrupt. * And call scsi_softreset(). */scsi_hardreset(){ register int s;#ifdef DMAC_MAP_INIT register int i;#endif s = splscsi(); scsi_chipreset(); DMAC_WAIT0; int_stat1 = 0; int_stat2 = 0; SET_CMD(SCMD_AST_RST); /* assert RST signal */#ifdef DMAC_MAP_INIT if (dmac_map_init == 0) { dmac_map_init++; for (i = 0; i < NDMACMAP; i++) {# if defined(mips) && defined(CPU_SINGLE) dmac_gsel = CH_SCSI; dmac_ctag = (u_char)i; dmac_cmap = (u_short)0;# endif } }#endif splx(s);}/* * I/O port (sc_ioptr) bit assign * * Rf_PRT3 - <reserved> * Rf_PRT2 - <reserved> * Rf_PRT1 out Floppy Disk Density control * Rf_PRT0 out Floppy Disk Eject control */scsi_chipreset(){ register int s; register int iloop; register VOLATILE int save_ioptr; register VOLATILE int dummy; int s_int1, s_int2; s = splscsi();#if defined(mips) && defined(CPU_SINGLE) dmac_gsel = CH_SCSI; dmac_cwid = 4; /* initialize DMAC SCSI chan */ *(unsigned VOLATILE char *)PINTEN |= DMA_INTEN; dma_reset(CH_SCSI);#endif sc_envir = 0; /* 1/4 clock */ DMAC_WAIT0; save_ioptr = sc_ioptr; DMAC_WAIT0; last_cmd = SCMD_CHIP_RST; sc_comr = SCMD_CHIP_RST; /* reset chip */ DMAC_WAIT; (void) WAIT_STATR_BITCLR(R0_CIP); /* * SCMD_CHIP_RST command reset all register * except sc_statr<7:6> & sc_cmonr. * So, bit R0_MIRQ & R3_FNC will be not set. */ sc_idenr = SC_OWNID; DMAC_WAIT0; sc_intok1 = Ra_STO|Ra_RSL|Ra_ARBF; DMAC_WAIT0; sc_intok2 = Rb_FNC|Rb_SRST|Rb_PHC|Rb_SPE|Rb_RMSG; DMAC_WAIT0; sc_ioptr = save_ioptr; DMAC_WAIT; sc_moder = Rc_TMSL; /* RST drive time = 25.5 us */ DMAC_WAIT0; sc_timer = 0x2; DMAC_WAIT0; sc_moder = Rc_SPHI; /* selection timeout = 252 ms */ DMAC_WAIT0; sc_timer = SEL_TIMEOUT_VALUE; DMAC_WAIT0;#ifdef SCSI_1185AQ if (scsi_1185AQ) SET_CMD(SCMD_ENB_SEL); /* enable reselection */#endif int_stat1 &= ~R2_RSL; /* ignore RSL inter request */ splx(s);}scsi_softreset(){ register VOLATILE struct sc_chan_stat *cs; register struct scsi_stat *ss; register int (*handler)(); register int i;#ifdef mips extern struct sc_data sc_data[]; register struct sc_data *scdp;#endif wbq_actf = NULL; wbq_actl = NULL; ss = &scsi_stat; ss->wbc = 0; ss->wrc = 0; ss->ip = NULL; ss->ipc = -1; ss->dma_stat = OFF; pad_start = 0; for (i = 0; i < NTARGET; ++i) { if (i == SC_OWNID) continue; cs = &chan_stat[i]; cs->wb_next = NULL;#ifndef NOT_SUPPORT_SYNCTR sync_tr[i] = 0; /* asynchronous mode */#endif sel_stat[i] = SEL_WAIT; if (cs->sc != NULL) { if ((cs->sc->sc_istatus & INST_EP) == 0) cs->sc->sc_istatus = (INST_EP|INST_HE); cs->sc = NULL;#ifdef mips scdp = &sc_data[cs->chan_num]; MachFlushDCache(scdp->scd_scaddr, sizeof(struct scsi)); if (MACH_IS_USPACE(scdp->scd_vaddr)) { panic("scsi_softreset: user address is not supported"); } else if (MACH_IS_CACHED(scdp->scd_vaddr)) { MachFlushDCache(scdp->scd_vaddr, scdp->scd_count); } else if (MACH_IS_MAPPED(scdp->scd_vaddr)) {#ifdef notyet /* KU:XXX */ clean_k2dcache(scdp->scd_vaddr, scdp->scd_count);#else MachFlushCache();#endif }#endif /* mips */ if ((cs->intr_flg == SCSI_INTEN) && (handler = scintsw[i].sci_inthandler)) {#ifdef noyet /* KU:XXX */ intrcnt[INTR_SCSI00 + i]++;#endif (*handler)(scintsw[i].sci_ctlr); } } }}/* * RESELECTION interrupt service routine * ( RESELECTION phase ) */sc_resel(){ register struct sc_chan_stat *cs; register struct scsi_stat *ss; register VOLATILE int chan; register VOLATILE int statr; register int iloop; min_flag = 0; chan = (sc_idenr & R6_SID_MASK) >> SC_TG_SHIFT; if (chan == SC_OWNID) return; statr = sc_statr; DMAC_WAIT0; if (statr & R0_CIP) { if (last_cmd == SCMD_SEL_ATN) { /* * SELECTION command dead lock ? * save interrupt request */ while (sc_statr & R0_MIRQ) { DMAC_WAIT0; int_stat1 |= sc_intrq1; DMAC_WAIT0; int_stat2 |= sc_intrq2; DMAC_WAIT0; } scsi_chipreset(); } } cs = &chan_stat[chan]; if (cs->sc == NULL) { scsi_hardreset(); return; } if ((cs->sc->sc_istatus & INST_WR) == 0) { scsi_hardreset(); return; } ss = &scsi_stat; if (ss->ipc >= 0) { scsi_hardreset(); return; } ss->ip = cs; ss->ipc = chan; sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE; DMAC_WAIT0; iloop = 0; while ((int_stat2 & R3_FNC) == 0) { /* * Max 6 usec wait */ if (iloop++ > RSL_LOOP_CNT) { sel_stat[chan] = SEL_RSL_WAIT; return; } GET_INTR(&int_stat1, &int_stat2); } int_stat2 &= ~R3_FNC; sel_stat[chan] = SEL_SUCCESS; ss->wrc--; ss->dma_stat = OFF; pad_start = 0; cs->sc->sc_istatus |= INST_IP; cs->sc->sc_istatus &= ~INST_WR;#ifndef NOT_SUPPORT_SYNCTR sc_syncr = sync_tr[chan]; DMAC_WAIT0;#endif}/* * DISCONNECT interrupt service routine * ( Target disconnect / job done ) */sc_discon(){ register VOLATILE struct sc_chan_stat *cs; register struct scsi_stat *ss; register int (*handler)(); register VOLATILE int dummy;#ifdef mips extern struct sc_data sc_data[]; register struct sc_data *scdp;#endif /* * Signal reflection on BSY is occured. * Not Bus Free Phase, ignore. * * But, CXD1185Q reset INIT bit of sc_statr. * So, can't issue Transfer Information command. * * What shall we do ? Bus reset ? */ if ((int_stat2 & R3_DCNT) && ((sc_intok2 & Rb_DCNT) == 0)) return; sc_intok2 = Rb_FNC|Rb_SRST|Rb_PHC|Rb_SPE; DMAC_WAIT0; min_flag = 0; dummy = sc_cmonr; DMAC_WAIT0; if (dummy & R4_MATN) { SET_CMD(SCMD_NGT_ATN); (void) WAIT_STATR_BITSET(R0_MIRQ); GET_INTR(&int_stat1, &int_stat2); /* clear interrupt */ } if ((int_stat1 & R2_RSL) == 0) int_stat2 &= ~R3_FNC; ss = &scsi_stat; cs = ss->ip; if ((cs == NULL) || (ss->ipc < 0)) goto sc_discon_exit; if ((sel_stat[cs->chan_num] != SEL_SUCCESS) && (sel_stat[cs->chan_num] != SEL_TIMEOUT)) printf("sc_discon: eh!\n"); /* * indicate abnormal terminate */ if ((cs->sc->sc_istatus & (INST_EP|INST_WR)) == 0) cs->sc->sc_istatus |= (INST_EP|INST_PRE|INST_LB); cs->sc->sc_istatus &= ~INST_IP; ss->dma_stat = OFF; pad_start = 0; ss->ip = NULL; ss->ipc = -1; if ((cs->sc->sc_istatus & INST_WR) == 0) { if (perr_flag[cs->chan_num] > 0) cs->sc->sc_istatus |= INST_EP|INST_PRE; cs->sc = NULL;#ifdef mips scdp = &sc_data[cs->chan_num]; MachFlushDCache(scdp->scd_scaddr, sizeof(struct scsi)); if (MACH_IS_USPACE(scdp->scd_vaddr)) { panic("sc_discon: user address is not supported"); } else if (MACH_IS_CACHED(scdp->scd_vaddr)) { MachFlushDCache(scdp->scd_vaddr, scdp->scd_count); } else if (MACH_IS_MAPPED(scdp->scd_vaddr)) {#ifdef notyet /* KU:XXX */ clean_k2dcache(scdp->scd_vaddr, scdp->scd_count);#else MachFlushCache();#endif }#endif /* mips */ if ((cs->intr_flg == SCSI_INTEN) && (handler = scintsw[cs->chan_num].sci_inthandler)) {#ifdef notyet /* KU:XXX */ intrcnt[INTR_SCSI00 + cs->chan_num]++;#endif (*handler)(scintsw[cs->chan_num].sci_ctlr); } }sc_discon_exit: sc_start();}/* * SCSI phase match interrupt service routine */sc_pmatch(){ register VOLATILE struct sc_chan_stat *cs; register VOLATILE int phase; register VOLATILE int phase2; register VOLATILE int cmonr; int_stat2 &= ~R3_FNC; /* XXXXXXXX */ cs = scsi_stat.ip; if (cs == NULL) return;# if defined(mips) && defined(CPU_SINGLE) dma_reset(CH_SCSI);# endif phase = sc_cmonr & SC_PMASK; DMAC_WAIT0; for (;;) { phase2 = phase; cmonr = sc_cmonr; DMAC_WAIT0; phase = cmonr & SC_PMASK; if (phase == phase2) { if ((phase == DAT_IN) || (phase == DAT_OUT)) break; else if (cmonr & R4_MREQ) break; } } scsi_stat.dma_stat = OFF; pad_start = 0; if (phase == COM_OUT) { min_flag = 0; if (cs->comflg != CF_SEND) cs->comflg = CF_SET; sc_cout(cs); } else { cs->comflg = CF_ENOUGH; sc_intok2 &= ~Rb_FNC; if (phase == MES_IN) { min_flag++; sc_min(cs); } else { min_flag = 0; switch (phase) { case MES_OUT: sc_mout(cs); break; case DAT_IN: case DAT_OUT: sc_dio(cs); break; case STAT_IN: sc_sin(cs); break; default: printf("SCSI%d: unknown phase\n", cs->chan_num); break; } } }}flush_fifo(){ register VOLATILE int dummy; VOLATILE int tmp; VOLATILE int tmp0; dummy = sc_ffstr; DMAC_WAIT0; if (dummy & R5_FIFOREM) { /* * flush FIFO */ SET_CMD(SCMD_FLSH_FIFO); tmp = 0; do { do { dummy = sc_statr; DMAC_WAIT0; } while (dummy & R0_CIP); GET_INTR(&tmp0, &tmp); /* clear interrupt */ } while ((tmp & R3_FNC) == 0); }}/* * SCSI command send routine */intsc_cout(cs) register struct sc_chan_stat *cs;{ register struct scsi *sc; register int iloop; register int cdb_bytes; register VOLATILE int dummy; register VOLATILE int statr; if (cs->comflg == CF_SET) { cs->comflg = CF_SEND; flush_fifo(); sc = cs->sc; switch (sc->sc_opcode & CMD_TYPEMASK) { case CMD_T0: cdb_bytes = 6; break; case CMD_T1: cdb_bytes = 10; break; case CMD_T5: cdb_bytes = 12; break; default: cdb_bytes = 6; sc_intok2 |= Rb_FNC; break; } /* * set 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; } else { cdb_bytes = 1; iloop = 0; do { dummy = sc_cmonr; DMAC_WAIT0; if ((dummy & SC_PMASK) != COM_OUT) return; statr = sc_statr; DMAC_WAIT0; if (statr & R0_MIRQ) return; } while ((dummy & R4_MREQ) == 0); statr = sc_statr; DMAC_WAIT0; if (statr & R0_MIRQ) return; } SET_CNT(cdb_bytes); SET_CMD(SCMD_TR_INFO|R0_TRBE); for (iloop = 0; iloop < cdb_bytes; iloop++) { do { dummy = sc_cmonr; DMAC_WAIT0; if ((dummy & SC_PMASK) != COM_OUT) return; } while ((dummy & R4_MREQ) == 0); statr = sc_statr; DMAC_WAIT0; if (statr & R0_MIRQ) return; sc_datr = *act_cmd_pointer++; do { dummy = sc_cmonr; DMAC_WAIT0; } while ((dummy & R4_MACK) != 0); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -