📄 scsi_kzq.c
字号:
kzqaddr->sii_dstat = SII_DNE;#ifdef mips wbflush();#endif mips sc->sc_szflags[targid] &= ~SZ_DID_DMA; /* Update the remaining dma count for this current transfer */ if(sc->sc_siidmacount[targid] > KZQ_MAX_DMA_XFER_LENGTH) { sc->sc_siidmacount[targid] -= (KZQ_MAX_DMA_XFER_LENGTH - kzqaddr->sii_dmlotc); } else sc->sc_siidmacount[targid] -= (sc->sc_siidmacount[targid] - kzqaddr->sii_dmlotc); if(retval >= kzq_wait_count) goto HANDLE_ABORT; else goto BEGIN_LOOP; } /* Wait for interrupt to signal DMA completion */ else { PRINTD(targid, 0x4, ("kzq_scsistart: COMMAND IN PROGRESS dma interrupt mode\n")); return(SZ_IP); } } else if(!sc->scsi_polled_mode) { return(SZ_IP); /* dont spin in here!!! */ }HANDLE_ABORT: /* Abort the current SCSI operation due to error */ PRINTD(targid, 0x10, ("kzq_scsistart: command aborted (bus=%d target=%d cmd=0x%x)\n", cntlr, targid, sc->sc_curcmd[targid])); PRINTD(targid, 0x10, ("", kzq_dumpregs(cntlr, 0))); flags = SZ_HARDERR | SZ_LOGCMD | SZ_LOGREGS; scsi_logerr(sc, 0, targid, SZ_ET_CMDABRTD, 0, 0, flags); kzq_reset(sc); kzqaddr->sii_cstat = 0xffff; kzqaddr->sii_dstat = 0xffff;#ifdef mips wbflush();#endif mips sc->sc_selstat[targid] = SZ_IDLE; sc->sc_active = 0; return(SZ_RET_ABORT);}/****************************************************************** * * Perform the arbitration/selection phases for the SII chip. * ******************************************************************/kzq_select_target(sc, targid)register struct sz_softc *sc;int targid;{ int cntlr = sc->sc_siinum; register struct kzq_regs *kzqaddr = (struct kzq_regs *)sc->sc_scsiaddr; int retval, i; int retries = 3; int sii_select_wait = 5000; /* Loop till retries exhausted */ for(i = 0; i < retries; i++) { /* RDAT FIX * Determine if reselections are currently enabled. If so, * disable them during the selection. */ sii_rse_flag = kzqaddr->sii_csr & SII_RSE; if (sii_rse_flag) { kzqaddr->sii_csr &= ~SII_RSE;#ifdef mips wbflush();#endif mips } /* Do a quick check on the bus to see if it is in the busy state. If BUSY or SEL is asserted, another device on the bus is in a selection phase. Return SZ_BUSBUSY. SZ_BUSBUSY can be returned and the statemachine can leave. This is a single Initiator bus, and a selection is either mine or a reselection, in which the interrupt handler will be called. */ if( (kzqaddr->sii_sc1 & (SII_SC1_BSY | SII_SC1_SEL)) !=0 ) { PRINTD(targid, 0x104, ("kzq_select_target: Bus BUSY on select of ID %d\n",targid)); /* RDAT FIX * Turn reselections back on before leaving. */ if (sii_rse_flag) { kzqaddr->sii_csr |= SII_RSE;#ifdef mips wbflush();#endif mips } return( SZ_BUSBUSY ); } /* * Begin the selection phase on the SII chip with or without * reselects. Setup the Selector Control Register and the * Command Register on the SII to select a target on the SCSI * bus. */ kzqaddr->sii_slcsr = targid;#ifdef mips wbflush();#endif mips kzqaddr->sii_comm = (SII_SELECT|SII_ATN); /* RDAT FIX * It should be safe now to enable reselections. */ if (sii_rse_flag) { kzqaddr->sii_csr |= SII_RSE; } PRINTD(targid, 0x104, ("kzq_select_target: starting select of ID %d\n",targid));#ifdef mips wbflush();#endif mips /* Start timer to wait for a select to occur */ SZWAIT_UNTIL((kzqaddr->sii_cstat & SII_SCH),sii_select_wait,retval); /* If a state change did occur then make sure we are connected */ if((kzqaddr->sii_cstat & SII_SCH) && !(kzqaddr->sii_cstat & SII_CON)) SZWAIT_UNTIL((kzqaddr->sii_cstat & SII_CON),kzq_wait_count,retval); /* Check for connection attempt */ if(kzqaddr->sii_cstat & SII_CON) { /* Check for a Reselection Attempt and handle it in "kzq_intr" */ if(kzqaddr->sii_cstat & SII_DST_ONBUS) { targid = (kzqaddr->sii_destat & SII_IDMSK); PRINTD(targid, 0x104, ("kzq_select_target: reselect of ID %d in progress\n", targid)); return(SZ_BUSBUSY); } /* Check for a Selection Attempt and handle it here */ else { kzqaddr->sii_cstat = SII_SCH;#ifdef mips wbflush();#endif mips targid = (kzqaddr->sii_slcsr & SII_IDMSK); PRINTD(targid, 0x104, ("kzq_select_target: target ID %d selected\n",targid)); sc->sc_active = (1 << targid); sc->sc_selstat[targid] = SZ_SELECT; if(!sc->scsi_polled_mode) { kzqaddr->sii_csr &= ~(SII_SLE | SII_RSE);#ifdef mips wbflush();#endif mips } /* Set the sii_dmctrl register to the rec/ack offset for the selected target. The sii_dmctrl needes to be set if/when data phase is entered. */ kzqaddr->sii_dmctrl = sc->sc_siireqack[targid];#ifdef mips wbflush();#endif mips return(SZ_SUCCESS); } } else { PRINTD(targid, 0x114, ( "kzq_select_target: select of ID %d failed pass %d\n", targid, i )); /* * Selection timed out, clear necessary bus signals and * abort the selection if the selection_in_progress bit * (SII_SIP) is set. We abort the selection attempt by * sending the DISCONNECT command. If the (SII_SIP) bit * is not set then we most likely have a RESELECT from * another target occuring. */ if(kzqaddr->sii_cstat & SII_SIP) { kzqaddr->sii_cstat = SII_SCH; kzqaddr->sii_comm = SII_DISCON;#ifdef mips wbflush();#endif mips SZWAIT_UNTIL((kzqaddr->sii_cstat & SII_SCH),sii_select_wait, retval); kzqaddr->sii_cstat = SII_SCH; kzqaddr->sii_comm = 0;#ifdef mips wbflush();#endif mips } } } return(SZ_RET_ABORT);}/****************************************************************** * * Get the currently active scsi target. * ******************************************************************/kzq_getactive_target(sc)register struct sz_softc *sc;{ int targid; for(targid=0; targid<NDPS; targid++) if(sc && sc->sc_active & (1 << targid)) { return(targid); } return(-1);}/****************************************************************** * * Perform the DATA IN/DATA OUT PHASE on the SII chip. * ******************************************************************/kzq_startdma(sc, iodir)register struct sz_softc *sc;int iodir;{ int cntlr = sc->sc_siinum; register struct kzq_regs *kzqaddr = (struct kzq_regs *)sc->sc_scsiaddr; SII_BUFF *stv; u_char *byteptr; char *bufp; int datacnt, i; int retval, offset; int tmp_phase; int tmp_state; int dmacount; struct format_params *fp; struct reassign_params *rp; struct read_defect_params *rdp; struct defect_descriptors *dd; struct mode_sel_sns_params *msp; struct io_uxfer *iox; int targid = kzq_getactive_target(sc); /* * Handle non READ/WRITE scsi commands that transfer data. */ if((sc->sz_opcode != SZ_WRITE && sc->sz_opcode != SZ_READ) && (sc->sz_opcode != SZ_WRITE_10) && (sc->sz_opcode != SZ_READ_10)) { byteptr = (u_char *)&sc->sz_dat[targid]; switch(sc->sz_opcode) { case SZ_MODSEL: byteptr = (u_char *)&sc->sc_dat[0]; datacnt = (int) sc->sz_modsel.pll;#ifdef NOTNOW datacnt = SZ_MODSEL_LEN; if((sc->sc_devtyp[targid] & SZ_TAPE) == 0) datacnt -= 2;#endif NOTNOW if(sc->sc_rzspecial[targid]) { msp = (struct mode_sel_sns_params *)sc->sc_rzparams[targid]; byteptr = (u_char *)sc->sc_rzaddr[targid]; datacnt = msp->msp_length; }#ifdef SZDEBUG /* JAG make this a subroutine with DEBUG */ PRINTD(targid, 0x20, ("kzq_startdma: mode select data:")); for(i=0; i < datacnt; i++) { PRINTD(targid, 0x20, (" %x", *(byteptr+i))); } PRINTD(targid, 0x20, ("\n"));#endif SZDEBUG break; case SZ_RQSNS: byteptr = (u_char *)&sc->sc_sns[targid]; datacnt = sc->sz_rqsns.alclen; break; case SZ_INQ: datacnt = SZ_INQ_MAXLEN; if(sc->sc_rzspecial[targid]) byteptr = (u_char *)sc->sc_rzaddr[targid]; break; case SZ_RDCAP: datacnt = SZ_RDCAP_LEN; break; case SZ_MODSNS:/* * Why was it this way? Fred -- 7/13/89 if(sc->sc_devtyp[targid] & SZ_TAPE) datacnt = SZ_MODSNS_LEN;*/ datacnt = (int) sc->sz_modsns.alclen; if(sc->sc_rzspecial[targid]) { msp = (struct mode_sel_sns_params *)sc->sc_rzparams[targid]; byteptr = (u_char *)sc->sc_rzaddr[targid]; datacnt = msp->msp_length; } break; case SZ_RECDIAG: datacnt = SZ_RECDIAG_LEN; break; case SZ_REASSIGN: rp = (struct reassign_params *)sc->sc_rzparams[targid]; byteptr = (u_char *)sc->sc_rzparams[targid]; datacnt = ((rp->rp_header.defect_len0 << 0) & 0x00ff) + ((rp->rp_header.defect_len1 << 8) & 0xff00) + 4; break; case SZ_FORMAT: dd = (struct defect_descriptors *)sc->sc_rzaddr[targid]; byteptr = (u_char *)sc->sc_rzaddr[targid]; datacnt = ((dd->dd_header.fu_hdr.defect_len0 << 0) & 0x00ff) + ((dd->dd_header.fu_hdr.defect_len1 << 8) & 0xff00) + 4; break; case SZ_RDD: rdp = (struct read_defect_params *)sc->sc_rzparams[targid]; byteptr = (u_char *)sc->sc_rzaddr[targid]; datacnt = rdp->rdp_alclen; break; case SZ_READL: case SZ_WRITEL: iox = (struct io_uxfer *)sc->sc_rzparams[targid]; byteptr = (u_char *)sc->sc_rzaddr[targid]; datacnt = iox->io_cnt; break; default: PRINTD(targid, 0x10, ("kzq_startdma: unknown scsi cmd 0x%x\n", sc->sz_opcode)); return(SZ_RET_ABORT); break; } /* * Setup softc structure entries for special SCSI DISK * commands that do dma. (FORMAT UNIT), (READ DEFECT DATA), * (REASSIGN BLOCK), (MODE SELECT), (MODE SENSE) and * (INQUIRY). */ if(sc->sc_rzspecial[targid] && (sc->sc_curcmd[targid] == sc->sc_actcmd[targid])) { if(!(sc->sc_szflags[targid] & SZ_DMA_DISCON)) { sc->sc_b_bcount[targid] = datacnt; sc->sc_bpcount[targid] = datacnt; sc->sc_bufp[targid] = (char *)byteptr; sc->sc_xfercnt[targid] = 0; } goto SETUP_DMA; } /* Put the data onto the scsi bus */ if(iodir == SZ_DMA_WRITE) { if(kzq_senddata(sc, byteptr, datacnt, 0) != SZ_SUCCESS) { return(SZ_RET_ABORT); } } /* Get the data from the scsi bus */ else { if(kzq_recvdata(sc, byteptr, datacnt) != SZ_SUCCESS) { return(SZ_RET_ABORT); } } } else {SETUP_DMA: /* * Start of DMA code for a READ or WRITE scsi command, setup * the count, the RAM buffer offset, and the DMA registers. */ sc->sc_iodir[targid] = iodir;/*XPRINTF(XPR_NFS, "sta: %x %x %x", iodir, sc->sc_fstate,sc->sc_siidmacount[targid],0);*/ kzqaddr->sii_comm &= ~(SII_INXFER | SII_DMA);#ifdef mips wbflush();#endif mips sc->sc_savcnt[targid] = 0; /* Handle the case of the DMA being disconnected */ if(sc->sc_szflags[targid] & SZ_DMA_DISCON) { sc->sc_szflags[targid] &= ~SZ_DMA_DISCON; kzq_restartdma(sc); } else { /* Handle the case of the DMA just starting */ /* Setup the dmacount and the offset into the RAM buffer */ sc->sc_siidmacount[targid] = sc->sc_bpcount[targid]; kzq_restartdma(sc); } } return(SZ_SUCCESS);}/****************************************************************** * * Perform the COMMAND PHASE on the SII chip. * ******************************************************************/kzq_sendcmd(sc)register struct sz_softc *sc;{ int cntlr = sc->sc_siinum; register struct kzq_regs *kzqaddr = (struct kzq_regs *)sc->sc_scsiaddr; u_char *byteptr; int datacnt, i; int cmd_type; int cmdcnt; int targid = kzq_getactive_target(sc); sc->sc_szflags[targid] = 0; sc->sc_savcnt[targid] = 0; sc->sc_status[targid] = 0xff; sc->sc_siidmacount[targid] = 0; byteptr = (u_char *)&sc->sz_command; cmd_type = *byteptr; /* Get the size of the scsi command */ cmdcnt = 6; if(((cmd_type >> 5) & 0x7) == 1) cmdcnt = 10;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -