📄 scsi_sii.c
字号:
("sii_scsistart: COMMAND IN PROGRESS dma poll mode\n"));#endif SZDEBUG siiaddr->sii_csr &= ~SII_IE; SZWAIT_UNTIL((siiaddr->sii_dstat & (SII_DNE|SII_MIS)),sii_wait_count,retval); SZWAIT_UNTIL((siiaddr->sii_dstat & (SII_DNE|SII_MIS)),sii_wait_count,retval); siiaddr->sii_comm &= ~(SII_INXFER | SII_DMA); siiaddr->sii_dstat = SII_DNE; sc->sc_szflags[targid] &= ~SZ_DID_DMA; /* Update the remaining dma count for this current transfer */ if(sc->sc_siidmacount[targid] > SII_MAX_DMA_XFER_LENGTH) sc->sc_siidmacount[targid] -= (SII_MAX_DMA_XFER_LENGTH - siiaddr->sii_dmlotc); else sc->sc_siidmacount[targid] -= (sc->sc_siidmacount[targid] - siiaddr->sii_dmlotc); if(retval >= sii_wait_count) goto HANDLE_ERROR; else goto BEGIN_LOOP; } /* Wait for interrupt to signal DMA completion */ else {#ifdef SZDEBUG PRINTD(targid, 0x8, ("sii_scsistart: COMMAND IN PROGRESS dma interrupt mode\n"));#endif SZDEBUG return(SZ_IP); } }HANDLE_ERROR: /* Abort the current SCSI operation due to error */#ifdef SZDEBUG PRINTD(targid, 0x4, ("sii_scsistart: command aborted (bus=%d target=%d cmd=0x%x)\n", cntlr, targid, sc->sc_curcmd[targid])); PRINTD(targid, 0x4, ("", sii_dumpregs(cntlr, 0)));#endif SZDEBUG flags = SZ_HARDERR | SZ_LOGCMD | SZ_LOGREGS; scsi_logerr(sc, 0, targid, SZ_ET_CMDABRTD, 0, 0, flags); if(!scsi_polled_mode) { scsi_logerr(sc, 0, -1, SZ_ET_RSTBUS, 2, 0, SZ_HARDERR); } sii_reset(sc); return(SZ_RET_RESET);}/****************************************************************** * * Name: sii_select_target * * Abstract: Perform the arbitration/selection phases for 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. * SZ_BUSBUSY Bus is busy, retry the command later. ******************************************************************/sii_select_target(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 retval, i; int retries = 3; int sii_select_wait = 2500; /* Loop till retries exhausted */ for(i=0; i<retries; i++) { /* * Check to see if the SII is already connected or is in * the selection process. */ if ((siiaddr->sii_cstat & (SII_CON | SII_SIP)) != 0) {#ifdef SZDEBUG PRINTD(targid, 0x1, ("sii_select_target: The SII is already connected\n"));#endif SZDEBUG return(SZ_BUSBUSY); } /* * Begin the arbitration/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. */#ifdef SZDEBUG PRINTD(targid, 0x1, ("sii_select_target: starting select of ID %d\n", targid));#endif SZDEBUG siiaddr->sii_slcsr = targid; siiaddr->sii_comm = (SII_SELECT|SII_ATN); /* * Start timer to wait for a state change to occur on the * SII. Wait approximately 250 ms for the target to assert * BUSY on the SCSI BUS and for the state change interrupt * bit (SII_SCH) to be set on the SII. The 250 ms value is * the selection timeout period as specified in the scsi * specification. (250 milliseconds is recommended) */ SZWAIT_UNTIL((siiaddr->sii_cstat & SII_SCH),sii_select_wait,retval);#ifdef SZDEBUG PRINTD(targid, 0x20, ("sii_select_target: (STATE select wait) start=%d end=%d\n", sii_select_wait, (sii_select_wait - retval)));#endif SZDEBUG /* * If a state change did occur (SII_SCH is set) then make * sure we are connected. We got a state change so the SII * has successfully SELECTED a target or was RESELECTED by * a disconnected target. */ if((siiaddr->sii_cstat & SII_SCH) && !(siiaddr->sii_cstat & SII_CON)) SZWAIT_UNTIL((siiaddr->sii_cstat & SII_CON),sii_select_wait,retval); /* Check for connection attempt */ if(siiaddr->sii_cstat & SII_CON) { /* Check for a Reselection Attempt and handle it in "sii_intr" */ if(siiaddr->sii_cstat & SII_DST_ONBUS) { targid = (siiaddr->sii_destat & SII_IDMSK);#ifdef SZDEBUG PRINTD(targid, 0x1, ("sii_select_target: reselect of ID %d has occurred\n", targid));#endif SZDEBUG return(SZ_BUSBUSY); } /* Check for a Selection Attempt and handle it here */ else { siiaddr->sii_cstat = SII_SCH; targid = (siiaddr->sii_slcsr & SII_IDMSK);#ifdef SZDEBUG PRINTD(targid, 0x1, ("sii_select_target: select of ID %d succeeded\n",targid));#endif SZDEBUG sc->sc_active = (1 << targid); sc->sc_selstat[targid] = SZ_SELECT; if(!scsi_polled_mode) siiaddr->sii_csr &= ~(SII_SLE | SII_RSE); return(SZ_SUCCESS); } } else {#ifdef SZDEBUG PRINTD(targid, 0x4, ("sii_select_target: select of ID %d timed out (%d TIMES)\n", targid, i+1));#endif SZDEBUG /* * 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(siiaddr->sii_cstat & SII_SIP) { siiaddr->sii_cstat = SII_SCH; siiaddr->sii_comm = SII_DISCON; SZWAIT_UNTIL((siiaddr->sii_cstat & SII_SCH),sii_select_wait,retval);#ifdef SZDEBUG PRINTD(targid, 0x20, ("sii_select_target: (STATE discon wait) start=%d end=%d\n", sii_select_wait, (sii_select_wait - retval)));#endif SZDEBUG siiaddr->sii_cstat = SII_SCH; siiaddr->sii_comm = 0; } } } return(SZ_RET_ABORT);}/****************************************************************** * * Name: sii_startdma * * Abstract: Perform the DATA IN/DATA OUT PHASE on the SII chip. * * Inputs: * sc Pointer to sz_softc structure for this controller. * iodir The IO direction (DMA read or DMA write). * targid Target Id of device (0 - 7). * * Outputs: None. * * Return values: * SZ_SUCCESS Command completed successfully. * SZ_RET_ABORT Command aborted. ******************************************************************/sii_startdma(sc, iodir, targid)register struct sz_softc *sc;int iodir;int targid;{ int cntlr = sc - &sz_softc[0]; register struct sii_regs *siiaddr = (struct sii_regs *)cvqmsi + cntlr; u_char *byteptr; char *stv, *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; /* * 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; 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 PRINTD(targid, 0x2, ("sii_startdma: mode select data:")); for(i=0; i < datacnt; i++) { PRINTD(targid, 0x2, (" %x", *(byteptr+i))); } PRINTD(targid, 0x2, ("\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/16/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:#ifdef SZDEBUG PRINTD(targid, 0x4, ("sii_startdma: unknown scsi cmd 0x%x\n",sc->sz_opcode));#endif SZDEBUG 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(sii_senddata(sc, targid, byteptr, datacnt, 0) != SZ_SUCCESS) return(SZ_RET_ABORT); } /* Get the data from the scsi bus */ else { if(sii_recvdata(sc, targid, byteptr, datacnt) != SZ_SUCCESS) return(SZ_RET_ABORT); }#ifdef SZDEBUG if(sc->sz_opcode == SZ_RQSNS) PRINTD(targid, 0x4, ("", sii_print_sense(sc,targid)));#endif SZDEBUG } 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. */ siiaddr->sii_comm &= ~(SII_INXFER | SII_DMA); stv = sc->sc_rambuff + sc->sc_dboff[targid]; /* Handle the case of the DMA being disconnected */ if(sc->sc_szflags[targid] & SZ_DMA_DISCON) {#ifdef SZDEBUG PRINTD(targid, 0x1, ("sii_startdma: continuing DMA %s transfer of %d bytes\n", (iodir == SZ_DMA_WRITE)?"WRITE":"READ",sc->sc_bpcount[targid]));#endif SZDEBUG sc->sc_szflags[targid] &= ~SZ_DMA_DISCON; /* Setup the dmacount and the offset into the RAM buffer */ offset = sc->sc_bpcount[targid] - sc->sc_siidmacount[targid]; if(sc->sc_siidmacount[targid] > SII_MAX_DMA_XFER_LENGTH) dmacount = SII_MAX_DMA_XFER_LENGTH; else dmacount = sc->sc_siidmacount[targid]; } /* Handle the case of the DMA just starting */ else {#ifdef SZDEBUG PRINTD(targid, 0x1, ("sii_startdma: starting DMA %s transfer of %d bytes\n", (iodir == SZ_DMA_WRITE)?"WRITE":"READ",sc->sc_bpcount[targid]));#endif SZDEBUG /* Copy data to RAM buffer if DMA WRITE operation */ if(iodir == SZ_DMA_WRITE) { bufp = sc->sc_bufp[targid] + sc->sc_xfercnt[targid];/* bcopy (bufp, stv, sc->sc_b_bcount[targid]); */ blkcpy (bufp, stv, sc->sc_b_bcount[targid]); } /* Setup the dmacount and the offset into the RAM buffer */ sc->sc_siidmacount[targid] = sc->sc_bpcount[targid]; offset = 0; if(sc->sc_siidmacount[targid] > SII_MAX_DMA_XFER_LENGTH) dmacount = SII_MAX_DMA_XFER_LENGTH; else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -