📄 scsi_sii.c
字号:
*/ if (sii_rse_flag) { siiaddr->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. */ siiaddr->sii_slcsr = targid;#ifdef mips wbflush(); /* Flush SCSI id prior to starting selection. */#endif mips siiaddr->sii_comm = (SII_SELECT|SII_ATN); /* * It should be safe now to enable reselections. */ if (sii_rse_flag) { siiaddr->sii_csr |= SII_RSE; } PRINTD(targid, 0x104, ("sii_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((siiaddr->sii_cstat & SII_SCH),sii_select_wait,retval); /* If a state change did occur then make sure we are connected */ if((siiaddr->sii_cstat & SII_SCH) && !(siiaddr->sii_cstat & SII_CON)) SZWAIT_UNTIL((siiaddr->sii_cstat & SII_CON),sii_wait_count,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); PRINTD(targid, 0x104, ("sii_select_target: reselect of ID %d in progress\n", targid)); return(SZ_BUSBUSY); } /* Check for a Selection Attempt and handle it here */ else { siiaddr->sii_cstat = SII_SCH;#ifdef mips wbflush();#endif mips targid = (siiaddr->sii_slcsr & SII_IDMSK); PRINTD(targid, 0x104, ("sii_select_target: target ID %d selected\n",targid)); sc->sc_active = (1 << targid); sc->sc_selstat[targid] = SZ_SELECT; if(!sc->scsi_polled_mode) { siiaddr->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. */ siiaddr->sii_dmctrl = sc->sc_siireqack[targid];#ifdef mips wbflush();#endif mips return(SZ_SUCCESS); } } else { PRINTD(targid, 0x114, ( "sii_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(siiaddr->sii_cstat & SII_SIP) { siiaddr->sii_cstat = SII_SCH; siiaddr->sii_comm = SII_DISCON;#ifdef mips wbflush();#endif mips SZWAIT_UNTIL((siiaddr->sii_cstat & SII_SCH),sii_select_wait, retval); siiaddr->sii_cstat = SII_SCH; siiaddr->sii_comm = 0;#ifdef mips wbflush();#endif mips } } } return(SZ_RET_ABORT);}/****************************************************************** * * Get the currently active scsi target. * ******************************************************************/sii_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. * ******************************************************************/sii_startdma(sc, iodir)register struct sz_softc *sc;int iodir;{ int cntlr = sc->sc_siinum; register struct sii_regs *siiaddr = (struct sii_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 = sii_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, ("sii_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: case SZ_SNDDIAG: { if (sc->sc_devtyp[targid] & (SZ_DISK|SZ_CDROM)) { struct diagnostic_params *dp; dp = (struct diagnostic_params *) sc->sc_rzparams[targid]; datacnt = dp->dp_length; byteptr = (u_char *)sc->sc_rzaddr[targid]; } else { datacnt = SZ_RECDIAG_LEN; /* For tape driver. */ } 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; case SZ_READ_TOC: { register struct cd_toc *toc; toc = (struct cd_toc *)sc->sc_rzparams[targid]; datacnt = toc->toc_alloc_length; byteptr = (u_char *)sc->sc_rzaddr[targid]; break; } case SZ_READ_SUBCHAN: { register struct cd_sub_channel *sch; sch = (struct cd_sub_channel *)sc->sc_rzparams[targid]; datacnt = sch->sch_alloc_length; byteptr = (u_char *)sc->sc_rzaddr[targid]; break; } case SZ_READ_HEADER: { register struct cd_read_header *rh; rh = (struct cd_read_header *)sc->sc_rzparams[targid]; datacnt = rh->rh_alloc_length; byteptr = (u_char *)sc->sc_rzaddr[targid]; break; } case SZ_PLAYBACK_CONTROL: case SZ_PLAYBACK_STATUS: { register struct cd_playback *pb; pb = (struct cd_playback *)sc->sc_rzparams[targid]; datacnt = pb->pb_alloc_length; byteptr = (u_char *)sc->sc_rzaddr[targid]; break; } default: PRINTD(targid, 0x10, ("sii_startdma: unknown scsi cmd 0x%x\n", sc->sz_opcode)); return(SZ_RET_ABORT); break; } PRINTD (targid, 0x20, ("Using byteptr at 0x%x of datacnt %d bytes.\n", byteptr, datacnt)); /* * 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, byteptr, datacnt, 0) != SZ_SUCCESS) return(SZ_RET_ABORT); } /* Get the data from the scsi bus */ else { if(sii_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);*/ siiaddr->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; sii_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]; sii_restartdma(sc); } } return(SZ_SUCCESS);}/****************************************************************** * * Perform the COMMAND PHASE on the SII chip. * ******************************************************************/sii_sendcmd(sc)register struct sz_softc *sc;{ int cntlr = sc->sc_siinum; register struct sii_regs *siiaddr = (struct sii_regs *)sc->sc_scsiaddr; u_char *byteptr; int datacnt, i; int cmd_type; int cmdcnt; int targid = sii_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; cmdcnt = sz_cdb_length (cmd_type, targid);#ifdef SZDEBUG /* JAG make this a subroutine call with DEBUG */ PRINTD(targid, 0x20, ("sii_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(sii_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);}/****************************************************************** *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -