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

📄 sdc.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
	if(sdstart())		goto loop;	/* return keeping the 16K shared buffer */	return(VS_KEEP);bad:	bp->b_flags |= B_ERROR;	if(sd_st.sd_flags[unit] & DEV_EOM)		bp->b_error = ENOSPC;	dp = &sdutab[unit];	dp->b_actf = bp->av_forw;	iodone(bp);	goto loop;}/* This routine gets called after 700 m.sec timeout for RX23 motor to speed up  */sd_rx23wakeup(bp)register struct buf *bp;{	register int unit,maxsize,sz,xunit;	struct buf *dp;	unit = dkunit(bp);	sz = (bp->b_bcount+511) >> 9;	xunit = minor(bp->b_dev) & 07;        dsket_type = rx23_type(); /* find out the diskette type  */        if(dsket_type == DT_RX23H)	   sd_rx23htype(unit);        else	   sd_rx23dtype(unit);        if(sdst[dsket_type].sizes[xunit].nblocks == -1)	    maxsize = sd_st.ucb[unit].hostsize - sdst[dsket_type].sizes[xunit].blkoffs;        else	    maxsize = sdst[dsket_type].sizes[xunit].nblocks;        if (bp->b_blkno < 0 ||	    (dkblock(bp)+sz) > maxsize){  		if(sddebug) cprintf("%s%d:%s: Accessing beyond block %d\n",DEV_ID,unit,SOFT_ERR,maxsize);		sd_st.sd_flags[unit] |= DEV_EOM;		bp->b_flags |= B_ERROR;		if(sd_st.sd_flags[unit] & DEV_EOM)			bp->b_error = ENOSPC;		dp = &sdutab[unit];		dp->b_actf = bp->av_forw;		iodone(bp);		sdustart();        }	else {		sd_st.sd_blkno = bp->b_blkno + sd_st.ucb[unit].lbnbase + sdst[dsket_type].sizes[xunit].blkoffs;		if(sdstart())			sdustart();	}	return;}/* This routine checks if a diskette is in the drive and ready */sd_diskette(){	register struct nb1_regs *sdaddr = (struct nb1_regs *)qmem;	u_char cmd;	sdaddr->dkc_cmd = (SD_SETREG | UDC_DHEAD);	sdc_delay();	sdaddr->dkc_reg = 1;  /* assume RX33: head 1 valid only for RX33/RX23 */	sdc_delay();	sdaddr->dkc_reg = 0; /* UDC_DCYL */	sdc_delay();	sdaddr->dkc_cmd = (SD_SETREG | UDC_RTCNT);	sdc_delay();	sdaddr->dkc_reg = (RT_CNT | RT_INVRDY |RT_MOTOR  );    /* UDC_RTCNT */	sdc_delay();	sdaddr->dkc_reg = (MOD_HD | MOD_CHKCRC | MOD_SRTRXH);   /* UDC_MODE */	sdc_delay();	sdaddr->dkc_cmd = (SD_SETREG | UDC_TERM);	sdc_delay();	sdaddr->dkc_reg = (TERM_CRC | TERM_INT | TERM_DEL | TERM_WRPR |  TERM_WRFL);	cmd = (SD_SELECT | DTRT_RX33 | (0377&DRV_NUM2)); 	rx_reselect = 0;	if(sd_select(cmd,1)) {		mprintf("%s%d:%s: Drive Select failed\n",DEV_ID,sd_st.sd_drno,HARD_ERR); 		return(1);	}	if(rx_reselect == 1) {				/* The drive is not shown to be ready. So SELECT the *		 * drive with INVRDY 0 in UDC_RTCNT. */		sdaddr->dkc_cmd = (SD_SETREG | UDC_DHEAD);		sdc_delay();		sdaddr->dkc_reg = 1;  /* assume RX33: head 1 valid only for RX33 */		sdc_delay();		sdaddr->dkc_reg = 0; /* UDC_DCYL */		sdc_delay();		sdaddr->dkc_cmd = (SD_SETREG | UDC_RTCNT);		sdc_delay();		sdaddr->dkc_reg = (RT_CNT |RT_MOTOR );   /*UDC_RTCNT */		cmd = (SD_SELECT | DTRT_RX33 | (0377&DRV_NUM2)); 		if(sd_select(cmd,1)) {			mprintf("%s%d:%s: Drive Select failed\n",DEV_ID,sd_st.sd_drno,HARD_ERR); 			return(1);		}		/* The previous SELECT succeeded. Issue STEP command. *		 * The READY bit in UDC_DSTAT should now be 0. */		if(sd_rxcyl == 0)			cmd = SD_STEP;		else			cmd = (SD_STEP | STEP_OUT);		if(sd_step(cmd)) {			return(1);		}		/* Since STEP succeeded, there is a diskette in the *		 * drive. But the drive has to be selected again *		 * with INVRDY as 1 in UDC_RTCNT !! I GIVE UP!! */		sdaddr->dkc_cmd = (SD_SETREG | UDC_DHEAD);		sdc_delay();		sdaddr->dkc_reg = 1;  /* assume RX33: head 1 valid only for RX33 */		sdc_delay();		sdaddr->dkc_reg = 0; /* UDC_DCYL */		sdc_delay();		sdaddr->dkc_cmd = (SD_SETREG | UDC_RTCNT);		sdc_delay();		sdaddr->dkc_reg = (RT_CNT | RT_INVRDY |RT_MOTOR );   /*UDC_RTCNT */		sdc_delay();		sdaddr->dkc_reg = (MOD_HD | MOD_CHKCRC | MOD_SRTRXH);   /* UDC_MODE */		rx_reselect = 0;		cmd = (SD_SELECT | DTRT_RX33 | (0377&DRV_NUM2)); 		if(sd_select(cmd,1)) {			mprintf("%s%d:%s: Drive Select failed\n",DEV_ID,sd_st.sd_drno,HARD_ERR); 			return(1);		}	}	return(0);}/* This routine returns the RX23 diskette type */rx23_type(){	register struct nb1_regs *sdaddr = (struct nb1_regs *)qmem;	register struct nb_regs *sdiaddr = (struct nb_regs *)nexus;	register count = 0;	u_char status,udc_cstat,udc_dstat;	u_char udc_dhead,udc_dcyl,udc_scnt,udc_dsect,cmd;	int retry;		/*  Reset and restore the chip and drive, in order to		ensure that the following density test is reliable */	if (sd_diskette()) {		if (sddebug)        		cprintf ("drive is not ready\n");		}		else if (sddebug)        			cprintf ("drive is ready\n");	if (sd_restore(1)) {		if (sddebug) 			 cprintf ("Restore failed\n");		}		else if (sddebug)        			cprintf ("Restore Success\n");			/* read sector no. 18 to check if high density RX23 */	udc_dhead = 0;	udc_dcyl = 0;	udc_scnt = 1;	udc_dsect = 18;  /* High density */	cmd = (SD_RDLOG | RD_XFER);	for(retry=0; retry< 10; retry++) {		count = 0;		sd_poll = 1;		sdiaddr->nb_int_msk &= ~SINT_DC;		if(sd_rdwr(udc_dsect,udc_dhead,udc_dcyl,udc_scnt,cmd,0) ) {			if (sdiaddr->nb_int_reqclr & SINT_DC)			    sdiaddr->nb_int_reqclr = SINT_DC;			continue;		}		while(!(sdiaddr->nb_int_reqclr & SINT_DC))  {			DELAY(10);				if(++count >= LOOP_DELAY)				break;		}		if(count >= LOOP_DELAY) {			if (sdiaddr->nb_int_reqclr & SINT_DC)			    sdiaddr->nb_int_reqclr = SINT_DC;			continue;		}		sdc_delay(); /* to make sure status is correct */		status = sdaddr->dkc_stat;		if( (status & DKC_TERMCOD) != DKC_SUCCESS) {			sdaddr->dkc_cmd = (SD_SETREG | UDC_CSTAT);			sdc_delay();			udc_cstat = sdaddr->dkc_reg;  /* read UDC_CSTAT */			sdc_delay();			sdaddr->dkc_cmd = (SD_SETREG | UDC_DSTAT);			sdc_delay();			udc_dstat = sdaddr->dkc_reg;			cprintf("rx23_type: status = %o, udc_cstat = %o, udc_dstat = %o\n",status,udc_cstat,udc_dstat);			if (sdiaddr->nb_int_reqclr & SINT_DC)			    sdiaddr->nb_int_reqclr = SINT_DC;			continue;		}		break;	}	if(count >= LOOP_DELAY) {		sd_st.sd_cmd = SD_RESET; /* This should take care if the *					  * cancelled command finishes later */	}	if (sdiaddr->nb_int_reqclr & SINT_DC)	    sdiaddr->nb_int_reqclr = SINT_DC;	DELAY(1);	sdiaddr->nb_int_msk |= SINT_DC;	if(retry >=10) {		if(udc_cstat & CST_CMPER)			cprintf("%s%d:%s: compare error\n",DEV_ID,sd_st.sd_drno,HARD_ERR);		else if(udc_cstat & CST_ECCER)			cprintf("%s%d:%s: eccerror\n",DEV_ID,sd_st.sd_drno,HARD_ERR);		else if (udc_cstat & CST_SYNER) {			cprintf("%s%d:%s: syncerr\n",DEV_ID,sd_st.sd_drno,HARD_ERR);		}		cprintf("RX23 Double Density\n");		return(DT_RX23D);	}	/*cprintf("RX23  High Density\n");*/	return(DT_RX23H);  }/* This routine selects the drive (coded in cmd) before doing any I/O */sd_select(cmd,diskette)	u_char cmd;	int diskette;{	register struct nb1_regs *sdaddr = (struct nb1_regs *)qmem;	register struct nb_regs *sdiaddr = (struct nb_regs *)nexus;	register count = 0;	register fail_count=0;	u_char status,udc_dstat;	while(fail_count++ < 2) {		sdiaddr->nb_int_msk &= ~SINT_DC; 		count = 0; 		sdaddr->dkc_cmd = cmd;		if(diskette){			DELAY(75); /* for diskette max. of 64 microseconds */		} else {			DELAY(30);		}		while(!(sdaddr->dkc_stat & DKC_DONE)) { 			if(++count >= LOOP_DELAY)  				break; 		}		status = sdaddr->dkc_stat;		if(count >= LOOP_DELAY) {			sd_deselect();			DELAY(10);		}		else			break; 	} 	if(count >= LOOP_DELAY) {  		cprintf("sd_select: SELECT not done within count = %d\n",count);		sd_reset();		if (sdiaddr->nb_int_reqclr & SINT_DC)		    sdiaddr->nb_int_reqclr = SINT_DC;		DELAY(1);		sdiaddr->nb_int_msk |= SINT_DC;		return(1);	} 	if(diskette) {		DELAY(70);  		sdaddr->dkc_cmd = (SD_SETREG | UDC_DSTAT);		sdc_delay();		udc_dstat = sdaddr->dkc_reg;  /* read UDC_DSTAT */		if(sddebug >= 2) cprintf("sd_select: udc_dstat = %o,rx_reselect = %d\n",udc_dstat,rx_reselect);		if ((udc_dstat & DST_READY) != DST_READY) {			if(sddebug>=2) cprintf("sd_select: udc_dstat not ready\n");			if(rx_reselect == 0) {				rx_reselect = 1;			}			else {				rx_reselect = 0;				if (sdiaddr->nb_int_reqclr & SINT_DC)				    sdiaddr->nb_int_reqclr = SINT_DC;				DELAY(1);				sdiaddr->nb_int_msk |= SINT_DC;				return(1);			}		}	}	else {		if ((status & DKC_DATERR) == DKC_DATERR)  {			if(sddebug) cprintf("sd_select: dkc_stat = %o\n",status);			if (sdiaddr->nb_int_reqclr & SINT_DC)			    sdiaddr->nb_int_reqclr = SINT_DC;			DELAY(1);			sdiaddr->nb_int_msk |= SINT_DC;			return(1);		}	}	if (sdiaddr->nb_int_reqclr & SINT_DC)	    sdiaddr->nb_int_reqclr = SINT_DC;	DELAY(1);	sdiaddr->nb_int_msk |= SINT_DC;	return(0);}/* This routine deselcts all the drives */sd_deselect(){	register struct nb1_regs *sdaddr = (struct nb1_regs *)qmem;	register struct nb_regs *sdiaddr = (struct nb_regs *)nexus;	register count = 0;	sdiaddr->nb_int_msk &= ~SINT_DC; 	sdaddr->dkc_cmd = SD_DESEL;   	DELAY(64);	while(!(sdaddr->dkc_stat & DKC_DONE)) {		if(++count >= LOOP_DELAY)			break; 		;	}	if(count >= LOOP_DELAY) {		if(sddebug) cprintf("sd_deselect: DESELECT not done within count = %d, dkc_stat = %o\n",count,sdaddr->dkc_stat);		/* Reset the controller to cancel the DESELCT command in case it finishes */		sd_reset();		if (sdiaddr->nb_int_reqclr & SINT_DC)		    sdiaddr->nb_int_reqclr = SINT_DC;		DELAY(1);		sdiaddr->nb_int_msk |= SINT_DC;		return(1);	} 	if (sdiaddr->nb_int_reqclr & SINT_DC)	    sdiaddr->nb_int_reqclr = SINT_DC;	DELAY(1);	sdiaddr->nb_int_msk |= SINT_DC;	return(0);}/* This routine issues the RESTORE command to the controller */sd_restore(diskette){	register struct nb1_regs *sdaddr = (struct nb1_regs *)qmem;	register struct nb_regs *sdiaddr = (struct nb_regs *)nexus;	register count = 0;	u_char status;	sdiaddr->nb_int_msk &= ~SINT_DC; 	if(diskette)		sdaddr->dkc_cmd = SD_RESTOR;	else		sdaddr->dkc_cmd = (SD_RESTOR | REST_WAIT);	if(diskette){		DELAY(64); /* for diskette max. of 64 microseconds */	} else {		DELAY(30);	}	while(!(sdaddr->dkc_stat & DKC_DONE)) { 		if(++count >= LOOP_DELAY)			break; 	}	if(count >= LOOP_DELAY) {		if(sddebug) cprintf("sd_restore: RESTORE not done within count = %d\n",count);		/* Reset the controller to cancel the RESTORE command in case it finishes */		sd_reset();		if (sdiaddr->nb_int_reqclr & SINT_DC)		    sdiaddr->nb_int_reqclr = SINT_DC;		DELAY(1);		sdiaddr->nb_int_msk |= SINT_DC;		return(1);	} 	status = sdaddr->dkc_stat;	if(diskette) {		if( (status & DKC_TERMCOD) == DKC_VERERR) {			if(sddebug) cprintf("sd_restore: Diskette Not restored\n");			if (sdiaddr->nb_int_reqclr & SINT_DC)			    sdiaddr->nb_int_reqclr = SINT_DC;			DELAY(1);			sdiaddr->nb_int_msk |= SINT_DC;			return(1);		}	}	if (sdiaddr->nb_int_reqclr & SINT_DC)	    sdiaddr->nb_int_reqclr = SINT_DC;	DELAY(1);	sdiaddr->nb_int_msk |= SINT_DC;	return(0);}sd_step(cmd)	u_char cmd;{	register struct nb1_regs *sdaddr = (struct nb1_regs *)qmem;	register struct nb_regs *sdiaddr = (struct nb_regs *)nexus;	register count = 0;	u_char udc_dstat;	sdiaddr->nb_int_msk &= ~SINT_DC; 	sdaddr->dkc_cmd = cmd;	DELAY(64);	while(!(sdiaddr->nb_int_reqclr & SINT_DC)) {		DELAY(10);			if(++count >= LOOP_DELAY)			break; 		;	}	if(count >= LOOP_DELAY) {		if(sddebug) cprintf("sd_step: STEP not done within count = %d\n",count);		/* Reset the controller to cancel the STEP command in case it finishes */		sd_reset();		if (sdiaddr->nb_int_reqclr & SINT_DC)		    sdiaddr->nb_int_reqclr = SINT_DC;		DELAY(1);		sdiaddr->nb_int_msk |= SINT_DC;		return(1);	} 	sdaddr->dkc_cmd = (SD_SETREG | UDC_DSTAT);	sdc_delay();	udc_dstat = sdaddr->dkc_reg;  /* read UDC_DSTAT */	if(sddebug) cprintf("sd_step: udc_dstat = %o\n",udc_dstat);	if(rx_reselect == 1) {		rx_reselect = 0;		if( (udc_dstat & DST_READY) == DST_READY) {			mprintf("%s%d: Diskette Drive not ready\n",DEV_ID,sd_st.sd_drno);			if (sdiaddr->nb_int_reqclr & SINT_DC)			    sdiaddr->nb_int_reqclr = SINT_DC;			DELAY(1);			sdiaddr->nb_int_msk |= SINT_DC;			return(1);		}	}	if (sdiaddr->nb_int_reqclr & SINT_DC)	    sdiaddr->nb_int_reqclr = SINT_DC;	DELAY(1);	sdiaddr->nb_int_msk |= SINT_DC;	return(0);}

⌨️ 快捷键说明

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