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

📄 sdc.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
sdopen(dev,flag)	dev_t dev;	int flag;{	register int unit = minor(dev) >> 3;	register struct uba_device *ui;	register int i;					int sdstrategy();				if (unit >= nNSD || (ui = sddinfo[unit]) == 0 || ui->ui_alive == 0)		return (ENXIO);	sd_st.sd_flags[unit] = 0;	/* The diskette is checked to be on line everytime it is opened */	if( (unit == DRV_NUM2) && (flag & FNDELAY) )		sd_nodelay = 1;	else		sd_nodelay = 0;	if(unit == DRV_NUM2) {		dsket_type = -1;		sd_rxcyl = 0; 	}	/*	 *	See if we need to read in the partition table from the disk.	 *	The conditions we will have to read from the disk is if the 	 *	partition table valid bit has not been set for the volume	 *	is invalid.	 */	/*	 *	Assume that the default values before trying to	 *	see if the partition tables are on the pack. The	 *	reason that we do this is that the strategy routine	 *	is used to read in the superblock but uses the 	 *	partition info.  So we must first assume the	 *	default values.	 */	/* If opening drive 2 (Diskette), read the partition table every time 	 * since it can be either RX50/RX33/RX23H/RX23D diskette */	if ( (sd_part[unit].pt_valid == 0) || (unit == DRV_NUM2) ) {		for( i = 0; i <= 7; i++ ) {			sd_part[unit].pt_part[i].pi_nblocks = 				sdst[ui->ui_type].sizes[i].nblocks;			sd_part[unit].pt_part[i].pi_blkoff =				sdst[ui->ui_type].sizes[i].blkoffs;		}		sd_part[unit].pt_valid = PT_VALID;		/*	 *	Default partition are now set. Call rsblk to set	 *	the driver's partition tables, if any exists, from	 *	the "a" partition superblock	 */		rsblk( sdstrategy, dev, &sd_part[unit] ); 		if(sd_openerr) {			sd_openerr = 0;			if(sd_nodelay) {				sd_nodelay = 0;				return(0);			}			else				return(EIO);		}	}	return (0);}sdstrategy(bp)	register struct buf *bp;{	register int unit;	register struct buf *dp;	register struct pt *pt;	register s;	register xunit = minor(bp->b_dev) & 07;	register struct uba_device *ui;	register struct vsdev *vd;	vd = &vsdiskdev;	unit = dkunit(bp);	pt = &sd_part[unit];	if (unit >= nNSD) {		printf("%s%d:%s: sdstrategy: unit number wrong\n",DEV_ID,unit,SOFT_ERR);		goto bad;	}	ui = sddinfo[unit];	if (ui == 0 || ui->ui_alive == 0) 		goto bad;	/*	 *	Get partition table for the pack	 */	if ( sd_part[unit].pt_valid != PT_VALID )		if(sd_st.sd_flags[unit] & DEV_OFFLINE)			goto bad;		else			panic("sdstrategy: invalid partition table ");	s = spl5();	/* First link the buffer onto the drive queue */	dp = &sdutab[unit];	/* if it is a diskette, no sorting done since the type of diskette found	 * out only later */	if( unit == DRV_NUM2) {		if(dp->b_actf == 0)			dp->b_actf = bp;		else			dp->b_actl->av_forw = bp;		dp->b_actl = bp;		bp->av_forw = 0;	}	else {#define b_cylin b_resid		bp->b_cylin = (bp->b_blkno + sd_st.ucb[unit].lbnbase + pt->pt_part[xunit].pi_blkoff)/sdst[sd_st.sd_type[unit]].nspc;		disksort(dp,bp);	} 	/* Link the drive onto the controller queue */	if (dp->b_active == 0) {		dp->b_forw = NULL;		if (sdcbuf.b_actf == NULL )			sdcbuf.b_actf = dp;		else			sdcbuf.b_actl->b_forw = dp;		sdcbuf.b_actl = dp;		dp->b_active = 1;	}	if(sdcbuf.b_active == 0) {		sdcbuf.b_active = 1;		/* sdustart() gets called from vs_bufctl() which allows *		 * the disk controller and TK50 controller to share the *		 * 16K buffer */		vd->vsd_action = VS_ALLOC;		if ((cpu == C_VAXSTAR) && cvs_exmode_on)			sdustart();		else			vs_bufctl(vd);	}	splx(s);	return;bad:	bp->b_flags |= B_ERROR;	iodone(bp);	return;}sdustart(){	register struct buf *bp,*dp;	register int unit;	register struct pt *pt;				register npf,o;	register struct vsdev *vd;	struct pte *pte, *mpte;	struct proc *rp;	struct uba_device *ui;	int maxsize;	int xunit,i;	long sz;	unsigned v;	vd = &vsdiskdev;loop:	/* Check if any request pending for the controller */	if ((dp = sdcbuf.b_actf) == NULL) {		sdcbuf.b_active = 0;		/* deallocate the 16K shared buffer */		return(VS_DEALLOC);	}	/* Check if any request pending for the drive */	if ((bp = dp->b_actf) == NULL) {		dp->b_active = 0;		sdcbuf.b_actf = dp->b_forw;		goto loop;	}	/* Move drive to the end of the controller queue */	if( dp->b_forw != NULL ) {		sdcbuf.b_actf = dp->b_forw;		sdcbuf.b_actl->b_forw = dp;		sdcbuf.b_actl = dp;		dp->b_forw = NULL;	}	unit = dkunit(bp);	xunit = minor(bp->b_dev) & 07;	sz = (bp->b_bcount+511) >> 9;	sd_st.sd_buf = bp;	sd_st.sd_bleft = bp->b_bcount;	sd_st.ucb[unit].blk_type = BLK_HOST;	pt = &sd_part[unit];	/* following code figures out the proper ptes to	   remap into system space so interrupt routine can	   copy into buf structure. */ 	v = btop(bp->b_un.b_addr);	o = (int)bp->b_un.b_addr & PGOFSET;	npf = btoc(sd_st.sd_bleft + o) ;	rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc;	if ((bp->b_flags & B_PHYS) == 0)	{		sd_st.sd_addr = bp->b_un.b_addr;				}	else {		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 if ((bp->b_flags & B_SMEM)  &&	/* SHMEM */					((bp->b_flags & B_DIRTY) == 0))			pte = ((struct smem *)rp)->sm_ptaddr + v;		else {			pte = vtopte(rp, v);		}		sd_st.sd_addr = (char *)((int)SD_bufmap + (int)o); 		mpte = (struct pte *)sdbufmap; 		for (i = 0; i< npf; i++) {			if(pte->pg_pfnum == 0)				panic("sdc: zero pfn in pte");			*(int *)mpte++ = pte++->pg_pfnum | PG_V | PG_KW;			mtpr(TBIS, (char *) SD_bufmap + (i*NBPG)); 		}		*(int *)mpte = 0;		mtpr(TBIS, (char *)SD_bufmap + (i * NBPG));	}	switch(sd_st.sd_type[unit]) {  		case DT_RD31:		case DT_RD32:		case DT_RD33:		case DT_RD53:				case DT_RD54:			if(pt->pt_part[xunit].pi_nblocks == -1)				maxsize = sd_st.ucb[unit].hostsize - pt->pt_part[xunit].pi_blkoff;			else				maxsize = pt->pt_part[xunit].pi_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;				goto bad;			}			sd_st.sd_blkno = bp->b_blkno + sd_st.ucb[unit].lbnbase + pt->pt_part[xunit].pi_blkoff;			sd_st.sd_drno = unit;			break;		case DT_RX50:    		case DT_RX33:		    ui = sddinfo[unit];		    sd_st.sd_drno = unit;		    /* Check if the diskette type has to be detected. If the 		     * device is opened the diskette type will have to be		     * identified again. */		    if(dsket_type == DT_RX33) {  /* last diskette in was RX33 */			    if(sdst[DT_RX33].sizes[xunit].nblocks == -1)				maxsize = sd_st.ucb[unit].hostsize- sdst[DT_RX33].sizes[xunit].blkoffs;			    else				maxsize = sdst[DT_RX33].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;				    goto bad;			    }			    sd_st.sd_blkno = bp->b_blkno + sd_st.ucb[unit].lbnbase + sdst[DT_RX33].sizes[xunit].blkoffs;			    if(sdstart())				goto loop;			    /* return keeping the 16K shared buffer */			    return(VS_KEEP);		    } else if(dsket_type == DT_RX50){  /* last diskette in was RX50 */			    if(sdst[DT_RX50].sizes[xunit].nblocks == -1)				maxsize = sd_st.ucb[unit].hostsize- sdst[DT_RX50].sizes[xunit].blkoffs;			    else				maxsize = sdst[DT_RX50].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;				    goto bad;			    }			    sd_st.sd_blkno = bp->b_blkno + sd_st.ucb[unit].lbnbase + sdst[DT_RX50].sizes[xunit].blkoffs;			    if(sdstart())				goto loop;			    /* return keeping the 16K shared buffer */			    return(VS_KEEP);		    }		    /* The diskette type is unknown. First SELECT *		     * with parameters for RX33 (head 1). If the SELECT fails *		     * do the magic to see if the drive is really ready 		     * (done in sd_diskette) */		    if(sddebug) cprintf("sdustart: SELECTING DISKETTE ALL OVER\n");		    if(sd_diskette()) {			if(!sd_nodelay)printf("%s%d:%s: Drive select failed\n",DEV_ID,unit,HARD_ERR);			sd_st.sd_flags[unit] |= DEV_OFFLINE;			sd_st.sd_cmd = SD_RESET; /* Just to be safe so  that 						  * interrupt routine  will take care*/			sd_openerr = 1;			goto bad;		    }		    /* Delay 70 milliseconds  for the data recovery circuit to *		     * stabilize whenever diskette drive select line is changed *		     * from not-selected to selected */		    DELAY(70000); /* should be 70000?? */		    sd_restore(1);		    /* SEEK with head 1 to check if the diskette is an RX33. *		     * RX50 will fail with head 1 */		    if(sd_seek()) {			if(sddebug) cprintf("sdustart: assuming RX50 diskette\n");			/* UDC_RTCNT, UDC_MODE regs and DRIVE SELECT done 			 * in sd_rdwr() for RX50, since that seems to be the only			 * way to make it work, for now */			/* Change the drive parameters if the previous diskette *			 * type was not RX50 */			if(dsket_type != DT_RX50) {			    sd_rx50type(unit);  			    sd_st.sd_type[unit] = DT_RX50;			    dsket_type = DT_RX50;			    ui->ui_type = DT_RX50; 			}			if(sdst[DT_RX50].sizes[xunit].nblocks == -1)			    maxsize = sd_st.ucb[unit].hostsize - sdst[DT_RX50].sizes[xunit].blkoffs;			else			    maxsize = sdst[DT_RX50].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;				goto bad;			}			sd_st.sd_blkno = bp->b_blkno + sd_st.ucb[unit].lbnbase + sdst[DT_RX50].sizes[xunit].blkoffs;		    } else {			/* diskette is RX33 */			if(sddebug) cprintf("sdustart: RX33 diskette\n");			/* Change the drive parameters if the previous diskette *			 * type was not RX33 */			if(dsket_type != DT_RX33) {			    sd_rx33type(unit);			    sd_st.sd_type[unit] = DT_RX33;			    dsket_type = DT_RX33;			    ui->ui_type = DT_RX33; 			}			if(sdst[DT_RX33].sizes[xunit].nblocks == -1)			    maxsize = sd_st.ucb[unit].hostsize - sdst[DT_RX33].sizes[xunit].blkoffs;			else			    maxsize = sdst[DT_RX33].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;				goto bad;			}			sd_st.sd_blkno = bp->b_blkno + sd_st.ucb[unit].lbnbase + sdst[DT_RX33].sizes[xunit].blkoffs;			/* Delay for 500 milliseconds for the drive speed *			 * to stabilize at 360 rpm (for RX33) (only for proto)*/			DELAY(300000); 		    }		    break;		case DT_RX23H:		case DT_RX23D:		    ui = sddinfo[unit];		    sd_st.sd_drno = unit;		    /* Check if the diskette type has to be detected. If the 		     * device is opened the diskette type will have to be		     * identified again. */		    if( (dsket_type == DT_RX23H) || (dsket_type == DT_RX23D) ) {  /* there is a diskette present */			    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;				    goto bad;			    }			    sd_st.sd_blkno = bp->b_blkno + sd_st.ucb[unit].lbnbase + sdst[dsket_type].sizes[xunit].blkoffs;			    if(sdstart())				goto loop;			    /* return keeping the 16K shared buffer */			    return(VS_KEEP);		    } 		    /* Find if there is a diskette in the RX23 drive */		    if(sd_diskette()) {			if(!sd_nodelay) printf("%s%d:%s: Drive select failed\n",DEV_ID,unit,HARD_ERR);			sd_st.sd_flags[unit] |= DEV_OFFLINE;			sd_st.sd_cmd = SD_RESET;			sd_openerr = 1;			goto bad;		     }		     /* Delay for 700 milliseconds for the drive speed *		      * to stabilize at 300 rpm (for RX23) */		     timeout(sd_rx23wakeup,(caddr_t)bp,7*(hz/10));		     return(VS_KEEP);		     break;		default:			printf("%s%d:%s: Unknown Disk type : %d\n",DEV_ID,unit,SOFT_ERR,sd_st.sd_type[unit]);			goto bad;	}

⌨️ 快捷键说明

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