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

📄 scsi_sii.c

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