📄 scsi_asc.c
字号:
int flags; PRINTD(targid, SCSID_DISCONNECT, ("asc_mi: sc_message = 0x%x, sc_messgptr = 0x%x\n", sc->sc_message[targid], sc->sc_messgptr[targid])); /* Switch on the type of message received */ switch(sc->sc_message[targid]) { case SZ_CMDCPT: PRINTD(targid, SCSID_PHASE_STATE, ("asc_mi: SZ_CMDCPT message\n")); sc->sc_fstate = 0; sc->sc_szflags[targid] &= ~SZ_DID_DMA; sc->sc_actbp[targid] = BPFREE; sc->sc_dboff_busy[targid][0] = 0; sc->sc_dboff_busy[targid][1] = 0; /* Assumes one command at a time for each target */ if (sc->sc_dkn[targid] >= 0) dk_busy &= ~(1 << sc->sc_dkn[targid]); sc->scsi_completed[targid] = 1; break; case SZ_SDP: PRINTD(targid, (SCSID_PHASE_STATE | SCSID_DISCONNECT), ("\nasc_mi: ==> SZ_SDP message, sc_savcnt = %d\n\n", sc->sc_savcnt[targid])); sc->sc_szflags[targid] &= ~SZ_DID_DMA; sc->sc_dboff_len[targid][sc->sc_actbp[targid]] -= sc->sc_savcnt[targid]; ASC_LOADCNTR(ascaddr, 0); wbflush(); break; case SZ_DISCON: PRINTD(targid, (SCSID_PHASE_STATE | SCSID_DISCONNECT), ("asc_mi: SZ_DISCON message\n")); sc->sc_szflags[targid] |= SZ_WAS_DISCON; ASC_LOADCNTR(ascaddr, 0); wbflush();/* if ((sc->sc_prevpha == SZ_DATAI_PHA) || (sc->sc_prevpha == SZ_DATAO_PHA))*/ if (sc->sc_szflags[targid] & SZ_DMA_INTR) { sc->sc_szflags[targid] &= ~SZ_DMA_INTR; sc->sc_szflags[targid] |= SZ_DMA_DISCON; PRINTD(targid, SCSID_DISCONNECT, ("asc_mi: DMA_INTR -> DMA_DISCON\n")); } /* end if DMA_INTR */ break; case SZ_EXTMSG: PRINTD(targid, (SCSID_PHASE_STATE | SCSID_DISCONNECT), ("asc_mi: SZ_EXTMSG msg, targ = %x, sc_szflags = 0x%x\n", targid, sc->sc_szflags[targid])); sc->sc_extmessg[targid][0] = sc->sc_message[targid]; if (!(sc->sc_szflags[targid] & SZ_EXTMESSG)) { sc->sc_szflags[targid] |= SZ_EXTMESSG; sc->sc_messgptr [targid] = &sc->sc_extmessg [targid][0]; sc->sc_messg_len[targid] = -1; break; } /* end if */ else if (sc->sc_messg_len [targid] == 0) { PRINTD(targid, SCSID_DISCONNECT, ("\n===>>>> asc_mi: think we have complete ext. messg\n")); SZDEBUG_EXPAND(targid, &sc->sc_extmessg[targid][0], (int)(sc->sc_extmessg[targid][1]) + 2);#ifdef SZDEBUG DELAY(20000); /* time to look at message */#endif SZDEBUG /* * If the extended message is a Synchronous Data * Transfer Request message then set the REQ/ACK * offset for the current target otherwise reject * the message. * */ if (sc->sc_extmessg[targid][2] == SZ_SYNC_XFER) { if (sc->sc_extmessg[targid][4] > sc->asc_sync_offset) { sc->sc_extmessg[targid][4] = sc->asc_sync_offset; } sc->sc_ascreqack[targid] = sc->sc_extmessg[targid][4]; sc->sc_ascsyncper[targid] = asc_sync_xfer_reg; PRINTD(targid, SCSID_CMD_EXP, ("asc_mi: req ack offset = 0x%x, sync per = 0x%x\n", sc->sc_ascreqack[targid], sc->sc_ascsyncper[targid])); } /* end if SYNC_XFER */ else cprintf("asc_msgin: recv extmessg %x\n", sc->sc_extmessg[targid][2]); sc->sc_szflags[targid] &= ~SZ_EXTMESSG; if (sc->sc_alive[targid] == 0) { /* PROBING */ u_long messg = SZ_MSGREJ; cprintf("asc_mi: recvd SYNC req in probe\n"); asc_assert_attn = 1; asc_reject_message = 0; asc_FIFOsenddata(sc, ASC_XINFO, &messg, 1); break; } /* end if alive == 0 */ } /* end else */ break; case SZ_ID_NODIS: PRINTD(targid, SCSID_PHASE_STATE, ("asc_mi: SZ_ID_NODIS message\n")); break; case SZ_ID_DIS: PRINTD(targid, SCSID_PHASE_STATE, ("asc_mi: SZ_ID_DIS message\n")); break; case SZ_RDP: PRINTD(targid, SCSID_PHASE_STATE, ("asc_mi: SZ_RDP message\n")); break; case SZ_MSGREJ: PRINTD(targid, SCSID_PHASE_STATE, ("asc_mi: SZ_MSGREJ message\n")); break; case SZ_LNKCMP: PRINTD(targid, SCSID_PHASE_STATE, ("asc_mi: SZ_LNKCMP message\n")); break; case SZ_LNKCMPF: PRINTD(targid, SCSID_PHASE_STATE, ("asc_mi: SZ_LNKCMPF message\n")); break; default: PRINTD(targid, SCSID_PHASE_STATE, ("asc_mi: unknown message = 0x%x\n", sc->sc_message[targid]));#ifdef ASC_LOGERR flags = SZ_HARDERR | SZ_LOGMSG; scsi_logerr(sc, 0, targid, SZ_ET_BUSERR, 0x73, 0, flags);#endif ASC_LOGERR return(SZ_RET_ABORT); } /* end switch */ /* * Assert attention as long as the "asc_assert_attn" flag is * set. Attention gets deasserted during a message out phase * and the "asc_assert_attn" flags gets cleared. */ if (asc_assert_attn) { cprintf("asc_mi: asc_assert_atn TRUE, issuing ASC_SETATN\n"); ascaddr->asc_cmd = ASC_SETATN; wbflush(); } /* end if asc_assert_atn */ /* Note: this should generate a Disconnect Interrupt */ PRINTD(targid, (SCSID_FLOW | SCSID_DISCONNECT), ("asc_mi: issuing MSGACPT command\n")); sc->sc_asccmd = ASC_MSGACPT; ascaddr->asc_cmd = ASC_MSGACPT; wbflush(); return(SZ_SUCCESS);} /* end asc_msgin *//****************************************************************** * * name: asc_clear_discon_io_tasks * * abstract: Clear any disconnected io requests due to a bus reset. * * inputs: * * sc - the softc data structure * * outputs: none. * * return values: none. * ******************************************************************/asc_clear_discon_io_tasks(sc)register struct sz_softc *sc;{ int targid; int unit; struct buf *dp, *bp; /* Find out if any targets have I/O requests that disconnected */ for (targid = 0; targid < NDPS; targid++) { sc->sc_ascsentsync[targid] = 0; if (targid == sc->sc_sysid) /* skip initiator */ continue; if (sc->sc_alive[targid] == 0) /* non existent target */ continue; if (sc->sc_attached[targid] == 0) continue; unit = sc->sc_unit[targid]; dp = (struct buf *)&szutab[unit]; if (!dp->b_active) /* target not active */ continue; if (dp->b_actf == NULL) continue; /* no IO requests pending */ if (!(sc->sc_szflags[targid] & SZ_WAS_DISCON)) continue; /* was not disconnected */ PRINTD(targid, SCSID_ERRORS, ("asc_clear_discon_io_tasks: clearing target %d\n", targid)); printf("asc_clear_discon_io_tasks: clearing target %d\n", targid); bp = dp->b_actf; dp->b_actf = bp->av_forw; dp->b_active = 0; bp->b_resid = sc->sc_resid[targid]; bp->b_flags |= B_ERROR; bp->b_error = EIO; biodone(bp); sc->sc_xstate[targid] = SZ_NEXT; sc->sc_xevent[targid] = SZ_BEGIN; } /* end for */} /* end asc_clear_disc_io_tasks *//****************************************************************** * * name: asc_reset * * abstract: Reset the ASC chip. * * inputs: * * sc - the softc data structure * * outputs: none. * * return values: none. * ******************************************************************/asc_reset(sc)register struct sz_softc *sc;{ int cntlr = sc->sc_ascnum; ASC_REG *ascaddr = ASC_REG_ADDR; /* setup the register pointer */ int i, retval; char modname[TC_ROMNAMLEN+1]; char max[TC_ROMNAMLEN+1]; char min[TC_ROMNAMLEN+1]; int opt_type=0; /* Reset the ASC chip. */ ascaddr->asc_cmd = ASC_RESET; wbflush(); DELAY(25); /* Just in case... */ ascaddr->asc_cmd = ASC_NOOP; /* recommended for some parts.. */ wbflush(); DELAY(25); ascaddr->asc_srto = 0xff; /* Set select/reselect timeout to max*/ wbflush(); DELAY(25); /* Set the clock conversion factor up for 25 MHz system */ ascaddr->asc_so = 0; wbflush(); ascaddr->asc_ffss = 0; wbflush(); /* Set our SCSI id and indicate use parity */ ascaddr->asc_cnf1 = asc_def_cnf1 | sc->sc_sysid; wbflush(); DELAY(25); ascaddr->asc_cnf2 = asc_def_cnf2; wbflush(); DELAY(25); ascaddr->asc_cnf3 = asc_def_cnf3; wbflush(); DELAY(25); sc->asc_sync_offset = ASC_SYNC_OFFSET; /* check if 3MIN or 3MAX card */ if( cpu != DS_5500) { if( tc_addr_to_name(sc->sc_slotvaddr, modname) == -1) cprintf("asc_reset():tc_addr_to_name failed "); if( !strcmp(modname, "PMAZ-AA ") ) { opt_type = DS_5000; } else if( !strcmp(modname, "PMAZ-BA ") ) { opt_type = DS_5000_100; } else { cprintf("asc_reset: tc_... returned '%s', assuming 3MAX\n", modname); opt_type = DS_5000; } } sc->ioasicp = 0; /* default to no IOASIC in use */ switch (cpu) { case DS_5500: ascaddr->asc_ccf = 5; wbflush(); DELAY(25); break; case DS_5000: ascaddr->asc_ccf = 5; wbflush(); DELAY(25); break; case DS_5000_100: if(opt_type == DS_5000) { /* 3MAX option card */ ascaddr->asc_ccf = 3; wbflush(); DELAY(25); } else { /* 3MIN opt. or base controller */ ascaddr->asc_ccf = 5; wbflush(); DELAY(25); sc->ioasicp = (char *) PHYS_TO_K1( BASE_IOASIC ); /* to tell the isr that an ioasic is here */ /* This will have to be modified to point to other */ /* addresses when the IOASIC based option cards */ /* become available */ } break; default: panic ("asc_reset(): Unknown cpu type\n"); break; } /* * Assert SCSI bus reset for at least 25 Usec to clear the * world. */ sc->sc_asccmd = ASC_RSTBUS; ascaddr->asc_cmd = ASC_RSTBUS; wbflush(); DELAY(35); /* 25 - ok for 3MAX 35 - ok for 3MIN */ /* * Clear any pending interrupts from the reset. */ sc->sc_asc_ssr = ascaddr->asc_ss; sc->sc_asc_sr = ascaddr->asc_stat; sc->sc_asc_isr = ascaddr->asc_intr; /* will clear the interrupt */ asc_clear_discon_io_tasks(sc);/* RPS - removing to avoid re-kmalloc'ing memory in init routine. perhaps pdma should have a reset entry point as well. (*sc->dma_init)(sc);*/ DELAY(sz_wait_for_devices * 1000000);} /* end asc_reset *//****************************************************************** * * Name: ascintr * * Abstract: Handle interrupts from the 53c94 chip. Check for any * gross errors, then process the SCSI phase as reported in * the status register if the bus service bit is set. * Make sure that the sequence step register indicates * that the CDB bytes were sent. * When disconnect interrupt received AND not running * at probe time, start a new I/O. * * Interrupt status register processing: * * Disconnect - Ordinarily set after command completion * when the target disconnects. May be set to indicate * select/reselect timeout. * * Bus Service - Indicates that a target is requesting * an information transfer phase. * * Function Complete - When this bit is set, it indicates * that the Selection of the target is complete (although * the CDB may not have been transferred
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -