⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scsi_kzq.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
	    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 + -