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

📄 stc.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
     * is active.  Once REQ and BSY are asserted, the appropiate action     * is taken.      */    complete = 0;    do {	STWAIT_WHILE((((staddr->scs_curstat & SCS_REQ) != SCS_REQ) ||		((staddr->scs_curstat & SCS_BSY) != SCS_BSY)),1000000,retval);	if (retval >= 1000000) {#ifdef STDEBUG	    printd("\t\tstintr: SCS_REQ or SCS_BSY failed to set\n");	    stdumpregs();#endif STDEBUG#ifdef STDEBUG	ST_TRACK('H');#endif STDEBUG	    goto abort;	}	if (staddr->scs_status & SCS_PARERR) {	    mprintf ("st0: parity error\n");#ifdef STDEBUG	    printd("st0: parity error\n");#endif STDEBUG#ifdef STDEBUG	ST_TRACK('I');#endif STDEBUG	    goto abort;	}	else if (staddr->scs_curstat & SCS_RST) {	    mprintf ("st0: bus reset\n");#ifdef STDEBUG	    printd("st0: bus reset\n");#endif STDEBUG#ifdef STDEBUG	ST_TRACK('J');#endif STDEBUG	    goto abort;	}	i = staddr->scs_reset;	stiaddr->nb_int_reqclr = SCS_INT_TAPE;	/*	 * Zero the scs_mode register to clear all 	 * DMA status bits from the last DMA transfer	 */	staddr->scs_mode = 0;	/*	 * Turn off the SCS_INI_ENOUT driver	 */	inicmd_tmp &= ~SCS_INI_ENOUT;	staddr->scs_inicmd = inicmd_tmp;	/*	 * Read the bus phase, set the phase to match.	 */	staddr->scs_tarcmd = ((staddr->scs_curstat & SCS_PHA_MSK) >> 2);	switch (staddr->scs_curstat & SCS_PHA_MSK) {	case SCS_DATAO:#ifdef STDEBUG	    printd2("stintr: SCS_DATAO:\n");#endif STDEBUG	    sc->sc_prevpha = sc->sc_fstate;	    sc->sc_fstate = ST_DATAO_PHA;	    if (sc->st_opcode != ST_WRITE) {		byteptr = (u_char *)&sc->sc_dat[0];		if (sc->st_opcode == ST_MODSEL) {		    cmdcnt = ST_MODSEL_LEN;		}		else {		    if (sc->st_opcode == ST_INQ) {			cmdcnt = ST_CMD_LEN;		    }		    else {#ifdef STDEBUG			printd ("stintr: SCS_DATAO: unknown command 0x%x\n",			    sc->st_opcode);#endif STDEBUG#ifdef STDEBUG	ST_TRACK('K');#endif STDEBUG			goto abort;		    }		}		inicmd_tmp = SCS_INI_ENOUT;		staddr->scs_inicmd = inicmd_tmp;		/*		 * Send the command packet		 */#ifdef STDEBUG		printd2("Data Output Packet: \n");		/* 1 of 3 */#endif STDEBUG		for ( ; (cmdcnt > 0); cmdcnt--) {		    STWAIT_UNTIL(((staddr->scs_curstat & SCS_REQ) == SCS_REQ),10000,retval);		    if (retval >= 10000) {#ifdef STDEBUG			printd("stintr: SCS_DATAO: REQ not set\n");#endif STDEBUG#ifdef STDEBUG	ST_TRACK('L');#endif STDEBUG			goto abort;		    }#ifdef STDEBUG		    printd2 (" %x", *byteptr);			/* 2 of 3 */#endif STDEBUG		    staddr->scs_outdata = *byteptr++;		    inicmd_tmp |= SCS_INI_ACK;		    staddr->scs_inicmd = inicmd_tmp;		    STWAIT_UNTIL(((staddr->scs_curstat & SCS_REQ) != SCS_REQ),10000,retval);		    if (retval >= 10000) {#ifdef STDEBUG			printd("stintr: SCS_DATAO: REQ didn't go false\n");#endif STDEBUG#ifdef STDEBUG	ST_TRACK('N');#endif STDEBUG			goto abort;		    }		    inicmd_tmp &= ~SCS_INI_ACK;		    staddr->scs_inicmd = inicmd_tmp;		}#ifdef STDEBUG		printd2 ("\n");					/* 3 of 3 */#endif STDEBUG		break;	    }	    /* Copy the data from the 16K buffer to memory 	     * (user space or kernel space).  Will have to	     * set up own page table entries when copying to	     * user space.	     */	    /*	     * If bytecount is too large, throw out the transfer	     */	    if (bp->b_bcount > 16384) {		mprintf("st0: buffer too large\n");		DEV_UGH(sc->sc_device,0,"buffer too large");		bp->b_flags |= B_ERROR;#ifdef STDEBUG	ST_TRACK('P');#endif STDEBUG		goto abort;		break;	    }	    /*	     * set up the count;	     */	    if ((sc->sc_stflags & ST_WAS_DISCON) && (sc->sc_savcnt != 0)) {		sc->sc_bcount = -(sc->sc_savcnt);		staddr->scd_cnt = sc->sc_savcnt ;#ifdef STDEBUG		printd1("stintr#1: scd_cnt = 0x%x, sc_savcnt = 0x%x\n",			staddr->scd_cnt, sc->sc_savcnt);#endif STDEBUG	    }	    else {		sc->sc_bcount = (short)bp->b_bcount;		staddr->scd_cnt = (short)-(bp->b_bcount);	    }	    /*	     * Map the user page tables to my page tables (mpte)	     */		if ((cpu == C_VAXSTAR) && cvs_exmode_on)			stv = (char *)cvseddbmem + 0x10000;		else			stv = (char *)&staddr->nb_ddb[0];		if ((bp->b_flags & B_PHYS) == 0) {		    bufp = (char *)bp->b_un.b_addr;		}		else {		    /*	    	     * Map to user space		     */	    	    v = btop(bp->b_un.b_addr);		    o = (int)bp->b_un.b_addr & PGOFSET;		    npf = btoc(bp->b_bcount + o);		    rp = (bp->b_flags&B_DIRTY) ? &proc[2] : bp->b_proc;		    if (bp->b_flags & B_UAREA) {			pte = &rp->p_addr[v];		    }		    else if (bp->b_flags & B_PAGET) {			pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)];		    }		    else {			pte = vtopte(rp, v);		    }		    bufp = (char *)ST_bufmap + o;		    mpte = (struct pte *)stbufmap;		    for (i = 0; i < npf; i++) {			if (pte->pg_pfnum == 0)			    panic("st0: zero pfn in pte");			*(int *)mpte++ = pte++->pg_pfnum | PG_V | PG_KW;			mtpr(TBIS, (char *) ST_bufmap + (i * NBPG));		    }		    *(int *)mpte = 0;		    mtpr(TBIS, (char *) ST_bufmap + (i * NBPG));		}		sc->sc_stflags |= ST_MAPPED;		sc->sc_savstv = (long)stv;		sc->sc_savbufp = (long)bufp;	    /*	     * If the DMA transfer was interrupted by a disconnect	     * the remaining data to be transfered needs to be 	     * reloaded into the 16K buffer, and then another	     * DMA transfer started.  This only needs to be done	     * on a write DMA transfer.	     */	    if ((sc->sc_stflags & ST_WAS_DISCON) && (sc->sc_savcnt != 0)) {		/*		 * This is a quick way to subtract the the number of		 * bytes not transfered before the disconnect, from		 * the total number of bytes to transfer.  The result		 * is the number of bytes that need to be transfered.		 * sc->sc_savcnt is in two's complement form.  The		 * number of bytes to be transfered is used as an offset		 * and added to bufp to get the address of where to start		 * transfering data from.		 */		sc->sc_stflags &= ~ST_WAS_DISCON;		bufp =  bufp + (((short)bp->b_bcount + sc->sc_savcnt) & 0xffff);		bcopy (bufp, stv, -(sc->sc_savcnt));#ifdef STDEBUG		printd1("stintr: bufp offset = 0x%x, count = 0x%x\n",			(((short)bp->b_bcount + sc->sc_savcnt) & 0xffff),			-(sc->sc_savcnt));#endif STDEBUG	    }	    else {		bcopy (bufp, stv, bp->b_bcount);	    }	    /*	     * Enable interrupts, and DMA mode.      	     */	    staddr->scs_mode = (SCS_DMA | SCS_INTEOP | SCS_PARCK | SCS_INTPAR);	    inicmd_tmp = SCS_INI_ENOUT;	    staddr->scs_inicmd = inicmd_tmp;	    staddr->scd_dir = SCD_DMA_OUT;	    /*	     * Set the starting address in the 16K buffer.  This	     * is really an offset into the buffer.  It needs to	     * be written twice.  Whatever is in bits <7:0> gets	     * moved into bits <15:8> with the bits <15:14> zeroed,	     * and what ever you write into this register get put	     * into bits <7:0>.  Therefore, the first write contains	     * the bits destined for <15:8>, and the second write	     * contains the bits for <7:0>.	     */	    if ((cpu == C_VAXSTAR) && cvs_exmode_on) 		staddr->nb_scd_adr.l = 0x10000;	    else {		staddr->nb_scd_adr.c[0] = 0;		staddr->nb_scd_adr.c[0] = 0;	    }	    /*	     * Start the DMA transfer	     */	    staddr->scs_dmasend = 1;	    sc->sc_stflags |= (ST_DID_DMA | ST_RETD_KEEP);	    return(VS_KEEP);	    break;	case SCS_DATAI:#ifdef STDEBUG	    printd2("stintr: SCS_DATAI:\n");#endif STDEBUG	    sc->sc_prevpha = sc->sc_fstate;	    sc->sc_fstate = ST_DATAI_PHA;	    if (sc->st_opcode != ST_READ) {		byteptr = (u_char *)&sc->sc_sns;		switch (sc->st_opcode) {		    case ST_RQSNS:			num_expected = ST_RQSNS_LEN;			break;		    case ST_INQ:			num_expected = ST_INQ_LEN;			byteptr = (u_char *)&sc->st_dat;			break;		    case ST_MODSNS:			num_expected = ST_MODSNS_LEN;			byteptr = (u_char *)&sc->st_dat;			break;		    case ST_RECDIAG:			num_expected = ST_RECDIAG_LEN;			byteptr = (u_char *)&sc->st_dat;			break;		    default:#ifdef STDEBUG			printd("stintr: SCS_DATAI: unexpected command = %x\n",				sc->st_opcode);#endif STDEBUG		    break;		}		inicmd_tmp = 0;		staddr->scs_inicmd = inicmd_tmp;		/*		 * Receive the command packet		 */#ifdef STDEBUG		printd2("Data In Packet:");				/* 1 of 3 */#endif STDEBUG		for ( ; (num_expected > 0); num_expected--) {		    STWAIT_UNTIL(((staddr->scs_curstat & SCS_REQ) == SCS_REQ),10000,retval);		    if (retval >= 10000) {#ifdef STDEBUG			printd("stintr: SCS_DATAI: REQ not set\n");#endif STDEBUG#ifdef STDEBUG	ST_TRACK('Q');#endif STDEBUG			goto abort;		    }		    *byteptr++ = staddr->scs_curdata;#ifdef STDEBUG		    printd2(" %x", staddr->scs_curdata);		/* 2 of 3 */#endif STDEBUG		    inicmd_tmp |= SCS_INI_ACK;		    staddr->scs_inicmd = inicmd_tmp;		    STWAIT_UNTIL(((staddr->scs_curstat & SCS_REQ) != SCS_REQ),10000,retval);		    if (retval >= 10000) {#ifdef STDEBUG			printd("stintr: SCS_DATAO: REQ didn't go false\n");#endif STDEBUG#ifdef STDEBUG	ST_TRACK('R');#endif STDEBUG			goto abort;		    }		    inicmd_tmp &= ~SCS_INI_ACK;		    staddr->scs_inicmd = inicmd_tmp;		}#ifdef STDEBUG		printd2("\n");					/* 3 of 3 */#endif STDEBUG		break;	    }	    /*	     * Start of DMA code.	     *	     * set up the count;	     */	    if ((sc->sc_stflags & ST_WAS_DISCON) && (sc->sc_savcnt != 0)) {		sc->sc_bcount = -(sc->sc_savcnt);		staddr->scd_cnt = sc->sc_savcnt ;#ifdef STDEBUG		printd1("stintr#2: scd_cnt = 0x%x, sc_savcnt = 0x%x\n",			staddr->scd_cnt, sc->sc_savcnt);#endif STDEBUG	    }	    else {		sc->sc_bcount = (short)bp->b_bcount;		staddr->scd_cnt = (short)-(bp->b_bcount);	    }	    /*	     * Enable interrupts, and DMA mode.  	     */	    staddr->scs_mode = (SCS_DMA | SCS_INTEOP | SCS_PARCK | SCS_INTPAR);	    staddr->scs_inicmd = 0;	    staddr->scd_dir = SCD_DMA_IN;	    /*	     * Set the starting address in the 16K buffer.  This	     * is really an offset into the buffer.  It needs to	     * be written twice.  Whatever is in bits <7:0> gets	     * moved into bits <15:8> with the bits <15:14> zeroed,	     * and what ever you write into this register get put	     * into bits <7:0>.  Therefore, the first write contains	     * the bits destined for <15:8>, and the second write	     * contains the bits for <7:0>.	     */	    if ((cpu == C_VAXSTAR) && cvs_exmode_on) 		staddr->nb_scd_adr.l = 0x10000;	    else {		staddr->nb_scd_adr.c[0] = 0;		staddr->nb_scd_adr.c[0] = 0;	    }	    /*	     * Start the DMA transfer	     */	    staddr->scs_dmaircv = 1;	    sc->sc_stflags |= (ST_DID_DMA | ST_RETD_KEEP);	    return(VS_KEEP);	    break;	case SCS_CMD:#ifdef STDEBUG	    printd2("stintr: SCS_CMD:\n");#endif STDEBUG	    sc->sc_prevpha = sc->sc_fstate;	    sc->sc_fstate = ST_CMD_PHA;	    /*	     * clear savecnt and stflags	     */	    sc->sc_stflags = 0;	    sc->sc_savcnt = 0;	    inicmd_tmp = SCS_INI_ENOUT;	    staddr->scs_inicmd = inicmd_tmp;	    byteptr = (u_char *)&sc->st_command;#ifdef STDEBUG	    if ((st_prev_cmd == ST_WFM) && (*byteptr != ST_SPACE)) {		printd1("Didn't space back over second filemark\n");	    }	    st_prev_cmd = *byteptr;	    printd2("cmd pkt: %x %x %x %x %x\n", *byteptr, *(byteptr + 1),		*(byteptr + 2), *(byteptr + 3), *(byteptr + 4), *(byteptr + 5));#endif STDEBUG	    /*	     * Send the command packet	     */	    for (cmdcnt = ST_CMD_LEN; (cmdcnt > 0); cmdcnt--) {		STWAIT_UNTIL(((staddr->scs_curstat & SCS_REQ) == SCS_REQ),10000,retval);		if (retval >= 10000) {#ifdef STDEBUG		    printd("stintr: SCS_CMD: REQ not set\n");#endif STDEBUG#ifdef STDEBUG	ST_TRACK('S');#endif STDEBUG		    goto abort;		}#ifdef STDEBUG		ST_CMDTRACK(*byteptr); #endif STDEBUG		staddr->scs_outdata = *byteptr++;		inicmd_tmp |= SCS_INI_ACK;		staddr->scs_inicmd = inicmd_tmp;		STWAIT_UNTIL(((staddr->scs_curstat & SCS_REQ) != SCS_REQ),10000,retval);		if (retval >= 10000) {#ifdef STDEBUG		    printd("stintr: SCS_CMD: REQ didn't go false\n");#endif STDEBUG#ifdef STDEBUG	ST_TRACK('U');#endif STDEBUG		    goto abort;		}		inicmd_tmp &= ~SCS_INI_ACK;		staddr->scs_inicmd = inicmd_tmp;	    }	    break;	case SCS_STATUS:#ifdef STDEBUG	    printd2("stintr: SCS_STATUS:\n");#endif STDEBUG	    sc->sc_prevpha = sc->sc_fstate;	    sc->sc_fstate = ST_STATUS_PHA;	    /*	     * Save the residual count if the command is a read	     * or a write.	     */	    if((sc->st_opcode==ST_READ)||(sc->st_opcode==ST_WRITE)) {/* Fix for rev 45 TZK50 *//*		if ((sc->sc_prevpha == ST_DATAI_PHA) ||		    (sc->sc_prevpha == ST_DATAO_PHA)) {*/		    stiaddr->nb_hltcod = 0;		    sc->sc_resid = -(staddr->scd_cnt);/*		}		else {		    sc->sc_resid = bp->b_bcount;		}*/	    }	    STWAIT_UNTIL(((staddr->scs_curstat & SCS_REQ) == SCS_REQ),10000,retval);	    if (retval >= 10000) {#ifdef STDEBUG		printd("stintr: SCS_STATUS: REQ didn't set\n");#endif STDEBUG#ifdef STDEBUG	ST_TRACK('V');#endif STDEBUG		goto abort;	    }	    sc->sc_status = staddr->scs_curdata;	    inicmd_tmp = SCS_INI_ACK;	    staddr->scs_inicmd = inicmd_tmp;#ifdef STDEBUG	    printd2("stintr: SCS_STATUS: ppha = 0x%x, status = 0x%x, scd_cnt = 0x%x\n",		sc->sc_prevpha, sc->sc_status, staddr->scd_cnt);#endif STDEBUG	    STWAIT_WHILE(((staddr->scs_curstat & SCS_REQ) == SCS_REQ),50000,retval);	    if (retval >= 50000) {#ifdef STDEBUG		printd("stintr: SCS_STATUS: REQ didn't go false\n");#endif STDEBUG#ifdef STDEBUG	ST_TRACK('W');#endif STDEBUG		goto abort;	    }	    inicmd_tmp = 0;	    staddr->scs_inicmd = inicmd_tmp;	    /*	     * Check the status	     */	    if (sc->sc_status != ST_GOOD) {		sc->sc_stflags |= ST_NEED_SENSE;	    }	    break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -