📄 scsi_sii.c
字号:
dmacount = sc->sc_siidmacount[targid]; } /* * Set the starting address in the 128K buffer. */ siiaddr->sii_dmaddrl = ((sc->sc_dboff[targid] + offset) & 0xffff); siiaddr->sii_dmaddrh = ((sc->sc_dboff[targid] + offset) >> 16); siiaddr->sii_dmlotc = dmacount; siiaddr->sii_dmabyte = sc->sc_siioddbyte[targid]; /* * Start the DMA transfer. */ sc->sc_szflags[targid] |= SZ_DID_DMA; tmp_phase = siiaddr->sii_dstat & SII_PHA_MSK; tmp_state = siiaddr->sii_cstat & SII_STATE_MSK; if(!scsi_polled_mode) siiaddr->sii_csr |= SII_IE; siiaddr->sii_comm = (SII_DMA | SII_INXFER | tmp_state | tmp_phase); } return(SZ_SUCCESS);}/****************************************************************** * * Name: sii_sendcmd * * Abstract: Perform the COMMAND PHASE on the SII chip. * * Inputs: * sc Pointer to sz_softc structure for this controller. * targid Target Id of device (0 - 7). * * Outputs: None. * * Return values: * SZ_SUCCESS Command completed successfully. * SZ_RET_ABORT Command aborted. ******************************************************************/sii_sendcmd(sc, targid)register struct sz_softc *sc;int targid;{ int cntlr = sc - &sz_softc[0]; register struct sii_regs *siiaddr = (struct sii_regs *)cvqmsi + cntlr; u_char *byteptr; int datacnt, i; int cmd_type; int cmdcnt; sc->sc_savcnt[targid] = 0; sc->sc_status[targid] = 0xff; sc->sc_siidmacount[targid] = 0; siiaddr->sii_dmlotc = 0; sii_sent_cmd = 1; byteptr = (u_char *)&sc->sz_command; cmd_type = *byteptr; cmdcnt = sz_cdb_length (cmd_type, targid);#ifdef SZDEBUG PRINTD(targid, 0x2, ("sii_sendcmd: (targid=%d) scsi cmd pkt:", targid)); for(i=0; i < cmdcnt; i++) { PRINTD(targid, 0x2, (" %x", *(byteptr+i))); } PRINTD(targid, 0x2, ("\n"));#endif SZDEBUG /* Put the scsi command onto the scsi bus */ if(sii_senddata(sc, targid, 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);}/****************************************************************** * * Name: sii_getstatus * * Abstract: Perform the STATUS PHASE on the SII chip. * * Inputs: * sc Pointer to sz_softc structure for this controller. * targid Target Id of device (0 - 7). * * Outputs: None. * * Return values: * SZ_SUCCESS Command completed successfully. * SZ_RET_ABORT Command aborted. ******************************************************************/sii_getstatus(sc, targid)register struct sz_softc *sc;int targid;{ int cntlr = sc - &sz_softc[0]; register struct sii_regs *siiaddr = (struct sii_regs *)cvqmsi + cntlr; /* Get the status byte from the scsi bus */ if(sii_recvdata(sc, targid, &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];#ifdef SZDEBUG PRINTD(targid, 0x1, ("sii_getstatus: status byte = 0x%x = ",sc->sc_status[targid])); PRINTD(targid, 0x1, ("", sii_print_status((int)sc->sc_status[targid])));#endif SZDEBUG /* Check the status */ if(sc->sc_status[targid] != SZ_GOOD) { sc->sc_szflags[targid] |= SZ_NEED_SENSE; } return(SZ_SUCCESS);}/****************************************************************** * * Name: sii_msgout * * Abstract: Perform the MESSAGE OUT PHASE on the SII chip. * * Inputs: * sc Pointer to sz_softc structure for this controller. * targid Target Id of device (0 - 7). * * Outputs: None. * * Return values: * SZ_SUCCESS Command completed successfully. * SZ_RET_ABORT Command aborted. ******************************************************************/sii_msgout(sc, targid)register struct sz_softc *sc;int targid;{ int cntlr = sc - &sz_softc[0]; register struct sii_regs *siiaddr = (struct sii_regs *)cvqmsi + cntlr; u_char messg; int retval, i; 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, ("sii_msgout: sending NOP Message\n"));#endif SZDEBUG /* Put the NOP Message onto the scsi bus */ sii_senddata(sc, targid, &messg, 1, 0); return(SZ_SUCCESS); } /* Clear the assert attention flag */ sc->sc_szflags[targid] &= ~SZ_ASSERT_ATN; /* Check if we need to send a Message Reject Message */ if(sc->sc_szflags[targid] & SZ_REJECT_MSG) { sc->sc_szflags[targid] &= ~SZ_REJECT_MSG; messg = SZ_MSGREJ;#ifdef SZDEBUG PRINTD(targid, 0x1, ("sii_msgout: sending Message Reject Message\n"));#endif SZDEBUG /* Put the Message Reject Message onto the scsi bus */ if(sii_senddata(sc, targid, &messg, 1, 0) != SZ_SUCCESS) return(SZ_RET_ABORT); } /* Check if we need to send a Bus Device Reset Message */ else if(sc->sc_szflags[targid] & SZ_RESET_DEV) { if(sc->sc_siireqack[targid] != 0) sc->sc_siisentsync[targid] = 0; messg = SZ_DEVRST;#ifdef SZDEBUG PRINTD(targid, 0x1, ("sii_msgout: sending Bus Device Reset Message\n"));#endif SZDEBUG /* Put the Bus Device Reset Message onto the scsi bus */ if(sii_senddata(sc, targid, &messg, 1, 0) != SZ_SUCCESS) return(SZ_RET_ABORT); } /* Check if we need to send an Abort Message */ else if(sc->sc_szflags[targid] & SZ_ABORT_CMD) { messg = SZ_ABT;#ifdef SZDEBUG PRINTD(targid, 0x1, ("sii_msgout: sending Abort Message\n"));#endif SZDEBUG /* Put the Bus Device Reset Message onto the scsi bus */ if(sii_senddata(sc, targid, &messg, 1, 0) != SZ_SUCCESS) return(SZ_RET_ABORT); } /* Send the Identify Message with or without disconnects */ else { /* Setup for disconnects or no disconnects */ if(scsi_polled_mode || sii_no_disconnects) 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]) {#ifdef SZDEBUG PRINTD(targid, 0x1, ("sii_msgout: sending Identify Message = 0x%x\n",messg));#endif SZDEBUG /* Put the Identify Message onto the scsi bus */ if(sii_senddata(sc, targid, &messg, 1, SII_ATN) != SZ_SUCCESS) return(SZ_RET_ABORT); /* Now setup the Synchronous Data Xfer Message */ sc->sc_siisentsync[targid] = 1; 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] = 25; sc->sc_extmessg[targid][4] = SII_SYNC;#ifdef SZDEBUG PRINTD(targid, 0x1, ("sii_msgout: sending Sync Data Transfer Message\n")); PRINTD(targid, 0x1, ("sii_msgout: extended message data:")); for(i=0; i<5; i++) { PRINTD(targid, 0x1, (" %x", sc->sc_extmessg[targid][i])); } PRINTD(targid, 0x1, ("\n"));#endif SZDEBUG /* Put the Synchronous Data Xfer Message onto the scsi bus */ if(!(siiaddr->sii_dstat & SII_MIS) && sii_senddata(sc, targid, &sc->sc_extmessg[targid][0], 4, SII_ATN) != SZ_SUCCESS) { if(siiaddr->sii_dstat & SII_MIS) return(SZ_SUCCESS); else return(SZ_RET_ABORT); } /* Send out the last byte of the Synchronous Data Xfer Message */ if(!(siiaddr->sii_dstat & SII_MIS) && sii_senddata(sc, targid, &sc->sc_extmessg[targid][4], 1, 0) != SZ_SUCCESS) { if(siiaddr->sii_dstat & SII_MIS) return(SZ_SUCCESS); else return(SZ_RET_ABORT); } } else {#ifdef SZDEBUG PRINTD(targid, 0x1, ("sii_msgout: sending Identify Message = 0x%x\n",messg));#endif SZDEBUG /* Put the Identify Message onto the scsi bus */ if(sii_senddata(sc, targid, &messg, 1, 0) != SZ_SUCCESS) return(SZ_RET_ABORT); } } return(SZ_SUCCESS);}/****************************************************************** * * Name: sii_msgin * * Abstract: Perform the MESSAGE IN PHASE on the SII chip. * * Inputs: * sc Pointer to sz_softc structure for this controller. * targid Target Id of device (0 - 7). * * Outputs: None. * * Return values: * SZ_SUCCESS Command completed successfully. * SZ_RET_ABORT Command aborted. ******************************************************************/sii_msgin(sc, targid)register struct sz_softc *sc;int targid;{ int cntlr = sc - &sz_softc[0]; register struct sii_regs *siiaddr = (struct sii_regs *)cvqmsi + cntlr; int len, i; int retval, save_dmlotc; int flags; /* * We must save the value in DMA Length Of Transfer Count * register if we are not using programmed io to receive the * message data. The reason for this is that if the message * is a SAVE DATA POINTER message than we will lose the saved * count in the DMA Length Of Transfer Count register when we * use DMA to receive the message. */ if(!sii_use_programmed_io) save_dmlotc = siiaddr->sii_dmlotc; /* Get the message from the scsi bus */ if(sii_recvdata(sc, targid, &sc->sc_message[targid], 1) != SZ_SUCCESS) return(SZ_RET_ABORT); /* Switch on the type of message recieved */ switch(sc->sc_message[targid]) { case SZ_CMDCPT:#ifdef SZDEBUG PRINTD(targid, 0x1, ("sii_msgin: SZ_CMDCPT message\n"));#endif SZDEBUG sc->sc_fstate = 0; sc->sc_szflags[targid] &= ~(SZ_DID_DMA | SZ_DMA_DISCON); /* Assumes one command at a time for each target */ if(sc->sc_dkn[targid] >= 0) dk_busy &= ~(1 << sc->sc_dkn[targid]); scsi_completed[targid] = 1; break; case SZ_SDP: if(!sii_use_programmed_io) sc->sc_savcnt[targid] = save_dmlotc; else sc->sc_savcnt[targid] = siiaddr->sii_dmlotc; siiaddr->sii_dmlotc = 0; sc->sc_szflags[targid] &= ~SZ_DID_DMA; if((sc->sc_prevpha != SZ_DATAI_PHA) && (sc->sc_prevpha != SZ_DATAO_PHA)) sc->sc_savcnt[targid] = 0;#ifdef SZDEBUG PRINTD(targid, 0x1, ("sii_msgin: SZ_SDP message: savcnt = %d\n", sc->sc_savcnt[targid]));#endif SZDEBUG /* Read the disconnect message now */ if(sii_recvdata(sc, targid, &sc->sc_message[targid], 1) != SZ_SUCCESS) return(SZ_RET_ABORT); if(sc->sc_message[targid] != SZ_DISCON) break; case SZ_DISCON:#ifdef SZDEBUG PRINTD(targid, 0x1, ("sii_msgin: SZ_DISCON message\n"));#endif SZDEBUG sc->sc_szflags[targid] |= SZ_WAS_DISCON; siiaddr->sii_dmlotc = 0; if (sc->sc_siidmacount[targid] != 0) { sc->sc_szflags[targid] |= SZ_DMA_DISCON; } break; case SZ_EXTMSG:#ifdef SZDEBUG PRINTD(targid, 0x1, ("sii_msgin: SZ_EXTMSG message\n"));#endif SZDEBUG sc->sc_extmessg[targid][0] = sc->sc_message[targid]; /* Read the extended message length */ if(sii_recvdata(sc, targid, &sc->sc_extmessg[targid][1], 1) != SZ_SUCCESS)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -