📄 scsi_kzq.c
字号:
#ifdef SZDEBUG /* JAG make this a subroutine call with DEBUG */ PRINTD(targid, 0x20, ("kzq_sendcmd: scsi cmd pkt:")); for(i=0; i < cmdcnt; i++) { PRINTD(targid, 0x20, (" %x", *(byteptr+i))); } PRINTD(targid, 0x20, (" ( %s )\n", scsi_cmdtable[cmd_type]));#endif SZDEBUG /* Put the scsi command onto the scsi bus */ if(kzq_senddata(sc, byteptr, cmdcnt, 0) != SZ_SUCCESS) { return(SZ_RET_ABORT); } /* Statistics update for READS and WRITES */ if((cmd_type == SZ_WRITE) || (cmd_type == SZ_READ) || (cmd_type == SZ_WRITE_10) || (cmd_type == SZ_READ_10)) { if(sc->sc_dkn[targid] >= 0) { dk_busy |= 1 << sc->sc_dkn[targid]; dk_xfer[sc->sc_dkn[targid]]++; dk_wds[sc->sc_dkn[targid]] += sc->sc_bpcount[targid] >> 6; } } return(SZ_SUCCESS);} /****************************************************************** * * Perform the STATUS PHASE on the SII chip. * ******************************************************************/kzq_getstatus(sc)register struct sz_softc *sc;{ int cntlr = sc->sc_siinum; register struct kzq_regs *kzqaddr = (struct kzq_regs *)sc->sc_scsiaddr; int targid = kzq_getactive_target(sc); /* Get the status byte from the scsi bus */ if(kzq_recvdata(sc, &sc->sc_status[targid], 1) != SZ_SUCCESS) return(SZ_RET_ABORT); /* Save the status byte for the error log */ if (sc->sc_curcmd[targid] == sc->sc_actcmd[targid]) sc->sc_statlog[targid] = sc->sc_status[targid]; PRINTD(targid, 0x24, ("kzq_getstatus: status byte = 0x%x = ", sc->sc_status[targid])); PRINTD(targid, 0x24, ("", kzq_print_status((int)sc->sc_status[targid]))); /* Check the status a switch table is used to handle future abilitys in status checking. */ switch( sc->sc_status[ targid ] ) { /* All went well onto the next phase. Fall through to the return() */ case SZ_GOOD : break; /* Set the SZ_NEED_SENCE flag, the state mach. will handle the rest. */ case SZ_CHKCND : sc->sc_szflags[targid] |= SZ_NEED_SENSE; break; /* Have to wait a bit for the target to be able to handle the request. Set the BUSYTARG flag to signal the interrupt handler of the BUSY condition. */ case SZ_BUSY : sc->sc_szflags[targid] |= SZ_BUSYTARG; /* set BUSY flag */ break; case SZ_INTRM : /* not handled for now */ case SZ_RESCNF : default : return(SZ_RET_ABORT); /* Assume bad failure for now */ break; } return(SZ_SUCCESS); /* every thing went well */}/****************************************************************** * * Perform the MESSAGE OUT PHASE on the SII chip. * ******************************************************************/kzq_msgout(sc)register struct sz_softc *sc;{ int cntlr = sc->sc_siinum; register struct kzq_regs *kzqaddr = (struct kzq_regs *)sc->sc_scsiaddr;#ifdef vax u_char messg;#endif vax#ifdef mips u_long messg;#endif mips int targid = kzq_getactive_target(sc); int lun = sc->sz_t_read.lun; /* * If the current state isn't SZ_SELECT then this message out * phase is incorrect. Send a NOP to get the target out of this * phase. NOTE -- this will need to be changed when we support * targets as initiators. This code is being added to get around * the sii's selection problem where the select command is ignored * leaving ATN asserted which causes the target to go to msgout. */ if(sc->sc_selstat[targid] != SZ_SELECT) { messg = SZ_NOP;#ifdef SZDEBUG PRINTD(targid, 0x1, ("kzq_msgout: sending NOP Message\n"));#endif SZDEBUG /* Put the NOP Message onto the scsi bus */ kzq_senddata(sc, &messg, 1, 0); return(SZ_SUCCESS); } /* Check if we need to send a Message Reject Message */ if(kzq_reject_message) { kzq_reject_message = 0; messg = SZ_MSGREJ; PRINTD(targid, 0x4, ("kzq_msgout: sending Message Reject Message\n")); /* Put the Message Reject Message onto the scsi bus */ if(kzq_senddata(sc, &messg, 1, 0) != SZ_SUCCESS) { return(SZ_RET_ABORT); } } /* Send the Identify Message with or without disconnects */ else { /* Clear the "kzq_assert_attn" flag */ kzq_assert_attn = 0; /* Setup for disconnects or no disconnects */ if(sc->scsi_polled_mode) messg = SZ_ID_NODIS | lun; /* Allow no disconnects */ else messg = SZ_ID_DIS | lun; /* Allow disconnects */ /* Check if we need to send a Synchronous DataXfer Message */ if(!sc->sc_siisentsync[targid]) { sc->sc_siisentsync[targid] = 1; PRINTD(targid, 0x4, ("kzq_msgout: sending Identify Message = 0x%x\n",messg)); /* Put the Identify Message onto the scsi bus */ if(kzq_senddata(sc, &messg, 1, SII_ATN) != SZ_SUCCESS) { return(SZ_RET_ABORT); } PRINTD(targid, 0x4, ("kzq_msgout: sending Sync Data Transfer Message\n")); /* Put the Synchronous Data Xfer Message onto the scsi bus */ sc->sc_extmessg[targid][0] = SZ_EXTMSG; sc->sc_extmessg[targid][1] = 0x3; sc->sc_extmessg[targid][2] = SZ_SYNC_XFER; sc->sc_extmessg[targid][3] = 63; /* 25, 12 is fast! */ sc->sc_extmessg[targid][4] = SII_SYNC; { int i; for(i=0; i < 4; i++) if(kzq_senddata(sc, &sc->sc_extmessg[targid][i], 1, SII_ATN) != SZ_SUCCESS) { if(i == 1) { /* For all those weird devices, can't do EXTMSG */ sc->sc_siireqack[targid] = 0; return(SZ_SUCCESS); } return(SZ_RET_ABORT); } } /* The following should probably not ever return failure since there are non-synchronous devices that will just reset the bus if given this message. The devices that this works on will succeed in any case. */ if(kzq_senddata(sc, &sc->sc_extmessg[targid][4], 1, 0) != SZ_SUCCESS) { /* For all those weird devices, can't do SYNC */ sc->sc_siireqack[targid] = 0; return(SZ_SUCCESS); } } else { PRINTD(targid, 0x4, ("kzq_msgout: sending default Identify Msg = 0x%x\n",messg)); /* Put the Identify Message onto the scsi bus */ messg = SZ_ID_NODIS | lun; /* Allow no disconnects */ if(kzq_senddata(sc, &messg, 1, 0) != SZ_SUCCESS) return(SZ_RET_ABORT); } } return(SZ_SUCCESS);}/****************************************************************** * * Perform the MESSAGE IN PHASE on the SII chip. * ******************************************************************/#ifdef ELDEBUG/* Set ID of target to cause DBBR message to be logged (on bus 0 only) */int sz_eldb_dbbr0 = -1;int sz_eldb_dbbr1 = -1;int sz_eldb_dbbr2 = -1;int sz_eldb_dbbr3 = -1;/* Set ID of target to cause unknown message error (bus 0 only) */int sz_eldb_buserr73 = -1;#endif ELDEBUGkzq_msgin(sc)register struct sz_softc *sc;{ int cntlr = sc->sc_siinum; register struct kzq_regs *kzqaddr = (struct kzq_regs *)sc->sc_scsiaddr; int len, i; int retval; int targid = kzq_getactive_target(sc); u_short olddmlotc = kzqaddr->sii_dmlotc; int flags; /* Get the message from the scsi bus */ if(kzq_recvdata(sc, &sc->sc_message[targid], 1) != SZ_SUCCESS) return(SZ_RET_ABORT);#ifdef ELDEBUG if ((cntlr == 0) && (targid == sz_eldb_buserr73)) { sc->sc_message[targid] = 0x5; /* SZ_ID initiator detected error */ sz_eldb_buserr73 = -1; }#endif ELDEBUG /* Switch on the type of message received */ switch(sc->sc_message[targid]) { case SZ_CMDCPT: PRINTD(targid, 0x4, ("kzq_msgin: SZ_CMDCPT message\n")); sc->sc_fstate = 0; sc->sc_szflags[targid] &= ~SZ_DID_DMA; sc->sc_actbp[targid] = -1; 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;#ifdef ELDEBUG if ((sc->sc_curcmd[targid] == SZ_READ) && (cntlr == 0) && (targid == sz_eldb_dbbr0)) { flags = SZ_HARDERR;/* ELDEBUG */ scsi_logerr(sc, sc->sc_bp[targid], targid, SZ_ET_DBBR, 0, 0, flags); sz_eldb_dbbr0 = -1; } if ((sc->sc_curcmd[targid] == SZ_READ) && (cntlr == 0) && (targid == sz_eldb_dbbr1)) { flags = SZ_HARDERR;/* ELDEBUG */ scsi_logerr(sc, sc->sc_bp[targid], targid, SZ_ET_DBBR, 1, 0, flags); sz_eldb_dbbr1 = -1; } if ((sc->sc_curcmd[targid] == SZ_READ) && (cntlr == 0) && (targid == sz_eldb_dbbr2)) { flags = SZ_SOFTERR;/* ELDEBUG */ scsi_logerr(sc, sc->sc_bp[targid], targid, SZ_ET_DBBR, 2, 0, flags); sz_eldb_dbbr2 = -1; } if ((sc->sc_curcmd[targid] == SZ_READ) && (cntlr == 0) && (targid == sz_eldb_dbbr3)) { flags = SZ_HARDERR;/* ELDEBUG */ scsi_logerr(sc, sc->sc_bp[targid], targid, SZ_ET_DBBR, 3, 0, flags); sz_eldb_dbbr3 = -1; }#endif ELDEBUG break; case SZ_SDP: PRINTD(targid, 0x4, ("kzq_msgin: SZ_SDP message\n")); sc->sc_savcnt[targid] = olddmlotc; sc->sc_szflags[targid] &= ~SZ_DID_DMA; sc->sc_dboff_len[targid][sc->sc_actbp[targid]] -= sc->sc_savcnt[targid]; kzqaddr->sii_dmlotc = 0; /* Read the disconnect message now */ if(kzq_recvdata(sc, &sc->sc_message[targid], 1) != SZ_SUCCESS) return(SZ_RET_ABORT); if(sc->sc_message[targid] != SZ_DISCON) break; /* FALL THROUGH */ case SZ_DISCON: PRINTD(targid, 0x4, ("kzq_msgin: SZ_DISCON message\n")); sc->sc_szflags[targid] |= SZ_WAS_DISCON; kzqaddr->sii_dmlotc = 0; if(sc->sc_siidmacount[targid] !=0 ) sc->sc_szflags[targid] |= SZ_DMA_DISCON; break; case SZ_EXTMSG: PRINTD(targid, 0x4, ("kzq_msgin: SZ_EXTMSG message\n")); sc->sc_extmessg[targid][0] = sc->sc_message[targid]; /* Read the extended message length */ if(kzq_recvdata(sc, &sc->sc_extmessg[targid][1], 1) != SZ_SUCCESS) return(SZ_RET_ABORT); len = (int)sc->sc_extmessg[targid][1]; /* * At this time the only extended messaged which is * supported is SZ_SYNC_XFER. If the incoming message * isn't a SZ_SYNC_XFER, assert ATN now! This will * prevent the target from becomming confused and * beleiving that the message was accepted. */ if(sc->sc_extmessg[targid][0] != SZ_SYNC_XFER) { sc->sc_szflags[targid] |= SZ_REJECT_MSG; kzqaddr->sii_comm |= SII_ATN; } /* Read the extended message */ if(kzq_recvdata(sc, &sc->sc_extmessg[targid][2], len) != SZ_SUCCESS) return(SZ_RET_ABORT);#ifdef SZDEBUG /* JAG make a subroutine w/DEBUG */ PRINTD(targid, 0x4, ("kzq_msgin: extended message:")); for(i=0; i<(len+2); i++) PRINTD(targid, 0x4, (" %x", sc->sc_extmessg[targid][i])); PRINTD(targid, 0x4, ("\n"));#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. Also reload the dmctrl register with * the new (possibly) offset. * */ if(sc->sc_extmessg[targid][0] == SZ_SYNC_XFER) { if(sc->sc_extmessg[targid][4] > SII_SYNC) sc->sc_extmessg[targid][4] = SII_SYNC; sc->sc_siireqack[targid] = sc->sc_extmessg[targid][4]; kzqaddr->sii_dmctrl = sc->sc_siireqack[targid]; } if(sc->sc_alive[targid] == 0) { /* PROBING */ u_long messg = SZ_MSGREJ; kzq_assert_attn = 1; kzq_reject_message = 0; kzq_senddata(sc, &messg, 1, SII_ATN); } break; case SZ_ID_NODIS: PRINTD(targid, 0x4, ("kzq_msgin: SZ_ID_NODIS message\n")); break; case SZ_ID_DIS: PRINTD(targid, 0x4, ("kzq_msgin: SZ_ID_DIS message\n")); break; case SZ_RDP: PRINTD(targid, 0x4, ("kzq_msgin: SZ_RDP message\n")); break; case SZ_MSGREJ: PRINTD(targid, 0x4, ("kzq_msgin: SZ_MSGREJ message\n")); break; case SZ_LNKCMP: PRINTD(targid, 0x4, ("kzq_msgin: SZ_LNKCMP message\n")); break; case SZ_LNKCMPF: PRINTD(targid, 0x4, ("kzq_msgin: SZ_LNKCMPF message\n")); break; default: flags = SZ_HARDERR | SZ_LOGMSG; scsi_logerr(sc, 0, targid, SZ_ET_BUSERR, 0x73, 0, flags); PRINTD(targid, 0x4, ("kzq_msgin: unknown message = 0x%x\n", sc->sc_message[targid])); return(SZ_RET_ABORT); } /* * Assert attention as long as the "kzq_assert_attn" flag is * set. Attention gets deasserted during a message out phase * and the "kzq_assert_attn" flags gets cleared. */ if(kzq_assert_attn) { kzqaddr->sii_comm |= SII_ATN; }#ifdef mips wbflush();#endif mips return(SZ_SUCCESS);}/****************************************************************** * * Send data to the scsi bus. * ******************************************************************/kzq_senddata(sc, data, count, attn)register struct sz_softc *sc;u_char *data;int count;int attn;{ int cnltr = sc->sc_siinum; register struct kzq_regs *kzqaddr = (struct kzq_regs *)sc->sc_scsiaddr; int retval; int tmp_state; int tmp_phase; int i; int targid = kzq_getactive_target(sc); /* Move the SII to the new phase */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -