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

📄 sdc.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
sd_seek(){	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(cpu == C_VAXSTAR)		sdaddr->dkc_cmd = (SD_SEEK | SK_STEP );	else		sdaddr->dkc_cmd = (SD_SEEK | SK_STEP | SK_VERFY);	DELAY(64); 	/* Cannot RESET the controller to cancel the comand if it 	 * did not complete within a time frame. */	while(!(sdiaddr->nb_int_reqclr & SINT_DC)) { 		DELAY(10);			if(++count >= LOOP_DELAY)			break;	}	if(count >= LOOP_DELAY) {		if(sddebug) cprintf("sd_seek: SEEK not done within count = %d\n",count);		sd_st.sd_cmd = SD_RESET; /* Since seek cannot be cancelled by a  					  * RESET, even if the seek cmd finishes					  * later, sdintr will ignore due to this */		if (sdiaddr->nb_int_reqclr & SINT_DC)		    sdiaddr->nb_int_reqclr = SINT_DC;		DELAY(1);		sdiaddr->nb_int_msk |= SINT_DC;		return(1);	}			if(cpu == C_VAXSTAR)  /* GMM */		DELAY(100);	status = sdaddr->dkc_stat;	if ( (status & DKC_TERMCOD) != DKC_SUCCESS) {  		if(sddebug) cprintf("sd_seek: command failed: status = %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);} /* Resets the controller */sd_reset(){	register struct nb1_regs *sdaddr = (struct nb1_regs *)qmem;	register count= 0;	sdaddr->dkc_cmd = SD_RESET;	DELAY(64);	while(count < DELAYTEN) {		if((sdaddr->dkc_stat & DKC_DONE) != 0)			break;		DELAY(10);		count++;	}	if (count == DELAYTEN){		cprintf("sd_reset: RESET failed\n");		sd_st.sd_cmd = SD_RESET; /* This should take care if the *					  * cancelled command finishes later */	}	sdaddr->dkc_cmd = (SD_SETREG | UDC_TERM);	sdc_delay();	sdaddr->dkc_reg = (TERM_CRC | TERM_INT | TERM_DEL | TERM_WRPR |  TERM_WRFL);	return(0);}/* * Reset the ST506 controller (if present). * The VMB boot driver requires this reset to kill off * any DMA that might be in progress at the time of a crash. * This routine is called from dumpsys() in machdep.c. * We wait 1 second for any DMA in progress to run down. */sdreset(){	register struct nb1_regs *sdaddr;	register int i;	if (mfpr(MAPEN) & 1)	/* memory management must be off, just */	   return;		/* return if m/m on.		       */	if ((vs_cfgtst & VS_SC_TYPE) != VS_ST506_SCSI)	    return;	sdaddr = (struct nb1_regs *)QMEMVAXSTAR;	/* delay about 1 second (DO NOT use DELAY() in physical mode */	for (i = 0; i < 5000000; i++) ;	sdaddr->dkc_cmd = SD_RESET;	for (i = 0; i < 5000; i++) ;	/* delay */}sdstart(){	register struct buf *bp, *dp;	register cylin;	register struct pt *pt;	register struct sdst *st;	struct uba_device *ui;	short sn;	u_char tmphd;	u_char   udc_dhead,udc_dcyl,udc_scnt,udc_dsect,cmd ;	int unit,xunit,logical_sn;	if( (bp = sd_st.sd_buf) == NULL) {		cprintf("bp is NULL\n");		return(1);	}	unit = dkunit(bp);	dp = &sdutab[unit];	xunit = minor(bp->b_dev) & 07;	pt = &sd_part[unit];	ui = sddinfo[unit];	if(sd_st.sd_blkno > (sd_st.ucb[unit].lbnbase + sd_st.ucb[unit].hostsize)) {		cprintf("%s%d:%s: Wrong block no %d\n",DEV_ID,unit,SOFT_ERR,sd_st.sd_blkno);		bp->b_flags |= B_ERROR;		dp->b_actf = bp->av_forw;		iodone(bp);		return(1);	}	if( (sd_st.sd_blkno - sd_st.ucb[unit].lbnbase) <		pt->pt_part[xunit].pi_blkoff) { 	        cprintf("%s%d:%s: Wrong partition: %d,block = %d\n",DEV_ID,unit,SOFT_ERR,xunit,sd_st.sd_blkno);		bp->b_flags |= B_ERROR;		dp->b_actf = bp->av_forw;		iodone(bp);		return(1);	} 	st = &sdst[sd_st.sd_type[unit]];	sd_st.ucb[unit].blk_type = BLK_HOST;	cylin = sd_st.sd_blkno/st->nspc ;	if(cylin >= st->ncyl) {		printf("%s%d:%s: Invalid cylinder: %d\n",DEV_ID,unit,HARD_ERR,sd_st.sd_cyl.sd_word);		panic("invalid cylinder");	}	if(unit == DRV_NUM2)		sd_rxcyl = cylin; 	if(sd_st.sd_type[unit] == DT_RX50) { /* use DEC's ten sector format */		sn = rx_table[sd_st.sd_blkno % 50];		if( ++cylin > 79)			cylin = 0;		sd_st.sd_hd = 0;   /* only one head */		sd_st.sd_nsect = st->nsect;		rx50nsect = (sd_st.sd_bleft + 511) >> 9;  /* required no. of sectors */		if(rx50nsect > sd_st.sd_nsect)			if(sd_st.sd_blkno % st->nsect)				rx50nsect = st->nsect - (sd_st.sd_blkno % st->nsect);			else				rx50nsect = sd_st.sd_nsect;		logical_sn = sd_st.sd_blkno%st->nspc;		logical_sn %= st->nsect;		if((logical_sn + rx50nsect) > st->nsect)			rx50nsect = st->nsect - logical_sn;		rx50blk = sd_st.sd_blkno;		if(rx50nsect == 1) {			sd_st.sd_nsect = 1;		} else {			sn = 1;			if(!(bp->b_flags & B_READ)) {			/* If to write, first read the full track and replace only the 			 * sectors to be written into */				sd_st.sd_cyl.sd_word = cylin;				tmphd = 0160 & (sd_st.sd_cyl.sd_byte[1] << 4);				sd_st.sd_cmd = SD_RDLOG;				cmd =  (SD_RDLOG | RD_XFER); 				udc_dsect = (0377&sn);  /* UDC_DSECT */ 				udc_dhead = (tmphd | (0017 & sd_st.sd_hd));  /* UDC_DHEAD */				udc_dcyl = sd_st.sd_cyl.sd_byte[0];  /* UDC_DCYL */				udc_scnt = 0377 & sd_st.sd_nsect ;				if(rx50read(udc_dsect,udc_dhead,udc_dcyl,udc_scnt,cmd,sd_st.ucb[unit].blk_type) ) {					bp->b_flags |= B_ERROR;					dp->b_actf = bp->av_forw;					iodone(bp);					return(1);				}			}		}		sd_st.sd_bcount = rx50nsect * SD_SIZE;		sd_st.sd_blkno += rx50nsect;	}	else {		sd_st.sd_hd = (sd_st.sd_blkno -(cylin*st->nspc))/st->nsect;		if(sd_st.sd_hd >= st->nheads) {			printf("%s%d:%s: Invalid head:%d \n",DEV_ID,unit,HARD_ERR,sd_st.sd_hd);			panic("invalid head");		}		sn = sd_st.sd_blkno%st->nspc;		sn %= st->nsect;		sd_st.sd_nsect = (sd_st.sd_bleft +511) >> 9;		if( (sn+sd_st.sd_nsect) > st->nsect) 			sd_st.sd_nsect = st->nsect - sn;		if(unit == DRV_NUM2)			sn++;  /* for diskette, sn starts with 1 */		sd_st.sd_bcount = sd_st.sd_nsect * SD_SIZE;		sd_st.sd_blkno += sd_st.sd_nsect;	}	start_sn = sn;  	sd_st.sd_cyl.sd_word = cylin;	tmphd = 0160 & (sd_st.sd_cyl.sd_byte[1] << 4);	if (bp->b_flags & B_READ) {		sd_st.sd_cmd = SD_RDLOG;		cmd =  (SD_RDLOG | RD_XFER); 	}	else {		sd_st.sd_cmd = SD_WRLOG;		if(sd_st.sd_type[unit] == DT_RX50)			cmd = (SD_WRLOG | RX50_PCOMP);		else if(sd_st.sd_type[unit] == DT_RX33)			cmd = (SD_WRLOG | RX33_PCOMP);		else {			if(cylin > sd_uib[unit].pccyl)				cmd = (SD_WRLOG | RD31_PCOMP);			else				cmd = SD_WRLOG ;		}		if((sd_st.sd_type[unit] == DT_RX50) && (rx50nsect > 1) )  			rx50transfer(sd_st.sd_addr,FILL);		else			sdtransfer(sd_st.sd_addr,FILL);	}	udc_dsect = (0377&sn);  /* UDC_DSECT */ 	udc_dhead = (tmphd | (0017 & sd_st.sd_hd));  /* UDC_DHEAD */	udc_dcyl = sd_st.sd_cyl.sd_byte[0];  /* UDC_DCYL */	udc_scnt = 0377 & sd_st.sd_nsect ;#ifdef BBR_TST	if(bp->b_flags & B_BAD) {			sd_st.ucb[sd_st.sd_drno].badsect = 0 ; 			sd_st.ucb[sd_st.sd_drno].badbn = sd_st.sd_blkno - sd_st.sd_nsect + sd_st.ucb[sd_st.sd_drno].badsect - sd_st.ucb[sd_st.sd_drno].lbnbase ; 			sd_st.ucb[sd_st.sd_drno].blk_type = BLK_BAL;			if(sdbbrdbug) cprintf("B_BAD: in sdstart: badsect = %d,badbn = %d,sd_blkno = %d, sd_nsect = %d\n",sn,sd_st.ucb[sd_st.sd_drno].badbn,sd_st.sd_blkno,sd_st.sd_nsect);			if(put_rbn(sd_st.ucb[sd_st.sd_drno].badbn)) {				cprintf("B_BAD: put_rbn failed\n");			} 			bbr_sleep = 0;			dp->b_actf = bp->av_forw;			vd->vsd_action = ST_WANTBACK;			if ((cpu == C_VAXSTAR) && cvs_exmode_on)				sdustart();			else			        vs_bufctl(vd); /*sdustart() gets called from vs_bufctl*/			return(0);	}#endif BBR_TST	if(sd_rdwr(udc_dsect,udc_dhead,udc_dcyl,udc_scnt,cmd,sd_st.ucb[unit].blk_type)) {	        if(cpu == C_VAXSTAR) cprintf("sdstart: sd_rdwr failed\n"); /* GMM */		if(sddebug) cprintf("sdstart: sd_rdwr failed\n");		bp->b_flags |= B_ERROR;		dp->b_actf = bp->av_forw;		iodone(bp);		return(1);	}	if(ui->ui_dk >= 0) {		dk_busy |= 1<<ui->ui_dk;		dk_xfer[ui->ui_dk]++;		dk_wds[ui->ui_dk] += sd_st.sd_bcount>>6;	}	return(0);}/* This routine does the actual read/write. All the registers are updated here   again just to be safe. (Sometimes causes syncerror otherwise) */sd_rdwr(udc_dsect,udc_dhead,udc_dcyl,udc_scnt,cmd,flag)	u_char udc_dsect,udc_dhead,udc_dcyl,udc_scnt,cmd;	short flag;{	register struct nb1_regs *sdaddr = (struct nb1_regs *)qmem;	register struct nb_regs *sdiaddr = (struct nb_regs *)nexus;	u_char sel_cmd; 	sdaddr->dkc_cmd = (SD_SETREG | UDC_DMA7);	sdc_delay();	if(flag) {  /* not host area block */		sdaddr->dkc_reg = rbn_addr1;	/* UDC_DMA7 */		sdc_delay();		sdaddr->dkc_reg = rbn_addr2;  /*UDC_DMA15 */	} else {		sdaddr->dkc_reg = 0;	/* UDC_DMA7 */		sdc_delay();		sdaddr->dkc_reg = 0;   /* UDC_DMA15 */	}	sdc_delay();	sdaddr->dkc_reg = 0;   /* UDC_DMA23 */	sdc_delay();	sdaddr->dkc_reg = udc_dsect;  /* UDC_DSECT */	sdc_delay();	sdaddr->dkc_reg = udc_dhead ;  /* UDC_DHEAD */	sdc_delay();	sdaddr->dkc_reg = udc_dcyl;  /* UDC_DCYL */	sdc_delay();	sdaddr->dkc_reg = udc_scnt;	sdc_delay();	if(sd_st.sd_drno == DRV_NUM2) {		if ((sd_st.sd_type[sd_st.sd_drno] == DT_RX50) || (sd_st.sd_type[sd_st.sd_drno] == DT_RX23D) )  { 			sdaddr->dkc_reg = (RT_CNT | RT_INVRDY |RT_MOTOR | RT_LOSPD);   /* UDC_RTCNT */			sdc_delay();			sdaddr->dkc_reg = (MOD_HD | MOD_CHKCRC | MOD_SRTRXL);  /* UDC_MODE */			sel_cmd = (SD_SELECT | DTRT_RX50 | DRV_NUM2); 		} else if( (sd_st.sd_type[sd_st.sd_drno] == DT_RX33) || (sd_st.sd_type[sd_st.sd_drno] == DT_RX23H) ) { 			sdaddr->dkc_reg = (RT_CNT | RT_INVRDY | RT_MOTOR); /* UDC_RTCNT */			sdc_delay();			sdaddr->dkc_reg = (MOD_HD | MOD_CHKCRC | MOD_SRTRXH);  /* UDC_MODE */			sel_cmd = (SD_SELECT | DTRT_RX33 | DRV_NUM2); 		}		else {			printf("sd_rdwr: Wrong type in Drive 2: %d\n",sd_st.sd_type[sd_st.sd_drno]);			return(1);		}		sdaddr->dkc_cmd = (SD_SETREG | UDC_TERM);		sdc_delay();		sdaddr->dkc_reg = (TERM_CRC | TERM_INT | TERM_DEL | TERM_WRPR |  TERM_WRFL);		rx_reselect = 0;		if(sd_select(sel_cmd,1)) {			printf("%s%d:%s: Drive select failed\n",DEV_ID,sd_st.sd_drno,HARD_ERR);			if(sd_poll) {				sd_poll = 0;				sdiaddr->nb_int_msk &= ~SINT_DC;			}			return(1);		}		if(sd_poll) {			sd_poll = 0;			sdiaddr->nb_int_msk &= ~SINT_DC;		}	}	else {		sdaddr->dkc_reg = RT_CNT;  /* UDC_RTCNT */		sdc_delay();		sdaddr->dkc_reg = (MOD_HD | MOD_CHKECC | MOD_SRTRDN);  /* 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);		sel_cmd = (SD_SELECT | DTRT_HDSK | sd_st.sd_drno);		if(sd_select(sel_cmd,0)) {			printf("%s%d:%s: Drive select failed\n",DEV_ID,sd_st.sd_drno,HARD_ERR);			sd_st.sd_flags[sd_st.sd_drno] |= DEV_OFFLINE;			if(sd_poll) {				sd_poll = 0;				sdiaddr->nb_int_msk &= ~SINT_DC;			}			return(1);		}		if(sd_poll) {			sd_poll = 0;			sdiaddr->nb_int_msk &= ~SINT_DC;		}	}	/*if( (cpu == C_VAXSTAR) && (sd_st.sd_drno == DRV_NUM2) ) {		if(sd_seek()) {			cprintf("RX23 seek failed\n");			return(1); 		}		DELAY(18000);	}    */	sdaddr->dkc_cmd = (SD_SETREG | UDC_DATA);	sdc_delay();	DELAY(100); 	sdaddr->dkc_cmd = cmd;	return(0);}rx50read(udc_dsect,udc_dhead,udc_dcyl,udc_scnt,cmd,type) u_char udc_dsect,udc_dhead,udc_dcyl,udc_scnt,cmd;short 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;	int retry;	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,type) ) {			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;			if(sddebug) cprintf("rx50read: 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)			printf("%s%d:%s: compare error\n",DEV_ID,sd_st.sd_drno,HARD_ERR);		else if(udc_cstat & CST_ECCER)			printf("%s%d:%s: eccerror\n",DEV_ID,sd_st.sd_drno,HARD_ERR);		else if (udc_cstat & CST_SYNER) {			printf("%s%d:%s: syncerr\n",DEV_ID,sd_st.sd_drno,HARD_ERR);		}		return(1);	}	return(0);}int	sd_stray = 0;	/* TODO1: debug */sdintr(star)	int star;{

⌨️ 快捷键说明

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