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

📄 up.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
			if (upaddr->uper1&UPER1_HCRC) {				if (upecc(ui, BSE))					return;			}	hard:			harderr(bp, "up");			printf("cn=%d tn=%d sn=%d cs2=%b er1=%b er2=%b\n",			        upaddr->updc, ((upaddr->upda)>>8)&077,			        (upaddr->upda)&037,				upaddr->upcs2, UPCS2_BITS,				upaddr->uper1, UPER1_BITS,				upaddr->uper2, UPER2_BITS);			bp->b_flags |= B_ERROR;		} else if (upaddr->uper2 & UPER2_BSE) {			if (upecc(ui, BSE))				return;			else				goto hard;		} else {			/*			 * Retriable error.			 * If a soft ecc, correct it (continuing			 * by returning if necessary.			 * Otherwise fall through and retry the transfer			 */			if ((upaddr->uper1&(UPER1_DCK|UPER1_ECH))==UPER1_DCK) {				if (upecc(ui, ECC))					return;			} else				um->um_tab.b_active = 0; /* force retry */		}		/*		 * Clear drive error and, every eight attempts,		 * (starting with the fourth)		 * recalibrate to clear the slate.		 */		upaddr->upcs1 = UP_TRE|UP_IE|UP_DCLR|UP_GO;		needie = 0;		if ((um->um_tab.b_errcnt&07) == 4 && um->um_tab.b_active == 0) {			upaddr->upcs1 = UP_RECAL|UP_IE|UP_GO;			sc->sc_recal = 0;			goto nextrecal;		}	}	/*	 * Advance recalibration finite state machine	 * if recalibrate in progress, through	 *	RECAL	 *	SEEK	 *	OFFSET (optional)	 *	RETRY	 */	switch (sc->sc_recal) {	case 1:		upaddr->updc = bp->b_cylin;		upaddr->upcs1 = UP_SEEK|UP_IE|UP_GO;		goto nextrecal;	case 2:		if (um->um_tab.b_errcnt < 16 || (bp->b_flags&B_READ) == 0)			goto donerecal;		upaddr->upof = up_offset[um->um_tab.b_errcnt & 017] | UPOF_FMT22;		upaddr->upcs1 = UP_IE|UP_OFFSET|UP_GO;		goto nextrecal;	nextrecal:		sc->sc_recal++;		um->um_tab.b_active = 1;		return;	donerecal:	case 3:		sc->sc_recal = 0;		um->um_tab.b_active = 0;		break;	}	/*	 * If still ``active'', then don't need any more retries.	 */	if (um->um_tab.b_active) {		/*		 * If we were offset positioning,		 * return to centerline.		 */		if (um->um_tab.b_errcnt >= 16) {			upaddr->upof = UPOF_FMT22;			upaddr->upcs1 = UP_RTC|UP_GO|UP_IE;			while (upaddr->upds & UPDS_PIP)				DELAY(25);			needie = 0;		}		um->um_tab.b_active = 0;		um->um_tab.b_errcnt = 0;		um->um_tab.b_actf = dp->b_forw;		dp->b_active = 0;		dp->b_errcnt = 0;		dp->b_actf = bp->av_forw;		bp->b_resid = (-upaddr->upwc * sizeof(short));		iodone(bp);		/*		 * If this unit has more work to do,		 * then start it up right away.		 */		if (dp->b_actf)			if (upustart(ui))				needie = 0;	}	as &= ~(1<<ui->ui_slave);	/*	 * Release unibus resources and flush data paths.	 */	ubadone(um);doattn:	/*	 * Process other units which need attention.	 * For each unit which needs attention, call	 * the unit start routine to place the slave	 * on the controller device queue.	 */	while (unit = ffs(as)) {		unit--;		/* was 1 origin */		as &= ~(1<<unit);		upaddr->upas = 1<<unit;		if (unit < UPIPUNITS && upustart(upip[sc21][unit]))			needie = 0;	}	/*	 * If the controller is not transferring, but	 * there are devices ready to transfer, start	 * the controller.	 */	if (um->um_tab.b_actf && um->um_tab.b_active == 0)		if (upstart(um))			needie = 0;	if (needie)		upaddr->upcs1 = UP_IE;}upread(dev, uio)	dev_t dev;	struct uio *uio;{	register int unit = minor(dev) >> 3;	if (unit >= nNUP)		return (ENXIO);	return (physio(upstrategy, &rupbuf[unit], dev, B_READ, minphys, uio));}upwrite(dev, uio)	dev_t dev;	struct uio *uio;{	register int unit = minor(dev) >> 3;	if (unit >= nNUP)		return (ENXIO);	return (physio(upstrategy, &rupbuf[unit], dev, B_WRITE, minphys, uio));}/*ARGSUSED*/upioctl(dev, cmd, data, flag)	dev_t dev;	int cmd;	caddr_t data;	int flag;{	struct pt *pt = (struct pt *)data;	int unit = minor(dev) >> 3;	register struct uba_device *ui;	register int nspc;	register int i;		int error;	switch (cmd) {	case DIOCGETPT:	/* 001 get partition table info */		/*		 *	Do a structure copy into the user's data area		 */		*pt = up_part[unit];		return(0);	case DIOCDGTPT:	/* 002 Return that default partition table */		ui = updinfo[unit];		/*		 * Get number sector per cylinder		 */		nspc = upst[ui->ui_type].nspc;		/*		 *  Get and store the default block count and offset		 */		for( i = 0; i <= 7; i++ ) {			pt->pt_part[i].pi_nblocks = 				upst[ui->ui_type].sizes[i].nblocks;			pt->pt_part[i].pi_blkoff =				upst[ui->ui_type].sizes[i].cyloff * nspc;		}		return(0);	case DIOCSETPT: /* 001 set the driver partition tables */		/*		 *	Only super users can set the pack's partition		 *	table		 */		if ( !suser() )			return(EACCES);				/*		 *	Before we set the new partition tables make sure		 *	that it will no corrupt any of the kernel data		 *	structures		 */		if ( ( error = ptcmp( dev, &up_part[unit], pt ) ) != 0 )			return(error);		/*		 *	Using the user's data to set the partition table		 *	for the pack		 */		up_part[unit] = *pt;		/*		 *	See if we need to update the superblock of the		 *	"a" partition of this disk		 */		ssblk(dev,pt);		/*		 *	Just make sure that we set the valid bit		 */		up_part[unit].pt_valid = PT_VALID;		return(0);	default:		return (ENXIO);	}}/* * Correct an ECC error, and restart the i/o to complete * the transfer if necessary.  This is quite complicated because * the transfer may be going to an odd memory address base and/or * across a page boundary. */upecc(ui, flag)	register struct uba_device *ui;	int flag;{	register struct updevice *up = (struct updevice *)ui->ui_addr;	register struct buf *bp = uputab[ui->ui_unit].b_actf;	register struct uba_ctlr *um = ui->ui_mi;	register struct upst *st;	struct uba_regs *ubp = ui->ui_hd->uh_uba;	register int i;	caddr_t addr;	int reg, bit, byte, npf, mask, o, cmd, ubaddr;	int bn, cn, tn, sn;	/*	 * Npf is the number of sectors transferred before the sector	 * containing the ECC error, and reg is the UBA register	 * mapping (the first part of) the transfer.	 * O is offset within a memory page of the first byte transferred.	 */	if (flag == CONT)		npf = bp->b_error;	else		npf = btop((up->upwc * sizeof(short)) + bp->b_bcount);	reg = btop(um->um_ubinfo&0x3ffff) + npf;	o = (int)bp->b_un.b_addr & PGOFSET;	mask = up->upec2;#ifdef UPECCDEBUG	printf("npf %d reg %x o %d mask %o pos %d\n", npf, reg, o, mask,	    up->upec1);#endif	bn = dkblock(bp);	st = &upst[ui->ui_type];	cn = bp->b_cylin;	sn = bn%st->nspc + npf;	tn = sn/st->nsect;	sn %= st->nsect;	cn += tn/st->ntrak;	tn %= st->ntrak;	ubapurge(um);	um->um_tab.b_active=2;	/*	 * action taken depends on the flag	 */	switch(flag){	case ECC:		npf--;		reg--;		mask = up->upec2;		printf("up%d%c: soft ecc sn%d\n", dkunit(bp),			'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf);		/*		 * Flush the buffered data path, and compute the		 * byte and bit position of the error.  The variable i		 * is the byte offset in the transfer, the variable byte		 * is the offset from a page boundary in main memory.		 */		i = up->upec1 - 1;		/* -1 makes 0 origin */		bit = i&07;		i = (i&~07)>>3;		byte = i + o;		/*		 * Correct while possible bits remain of mask.  Since mask		 * contains 11 bits, we continue while the bit offset is > -11.		 * Also watch out for end of this block and the end of the whole		 * transfer.		 */		while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {			struct pte pte;			pte = ubp->uba_map[reg + btop(byte)];			addr = ptob(pte.pg_pfnum) + (byte & PGOFSET);#ifdef UPECCDEBUG			printf("addr %x map reg %x\n",				addr, *(int *)(&ubp->uba_map[reg+btop(byte)]));			printf("old: %x, ", getmemc(addr));#endif			putmemc(addr, getmemc(addr)^(mask<<bit));#ifdef UPECCDEBUG			printf("new: %x\n", getmemc(addr));#endif			byte++;			i++;			bit -= 8;		}		if (up->upwc == 0)			return (0);		npf++;		reg++;		break;	case BSE:		/*		 * if not in bad sector table, return 0		 */		if ((bn = isbad(&upbad[ui->ui_unit], cn, tn, sn)) < 0)			return(0);		/*		 * flag this one as bad		 */		bp->b_flags |= B_BAD;		bp->b_error = npf + 1;#ifdef UPECCDEBUG		printf("BSE: restart at %d\n",npf+1);#endif		bn = st->ncyl * st->nspc -st->nsect - 1 - bn;		cn = bn / st->nspc;		sn = bn % st->nspc;		tn = sn / st->nsect;		sn %= st->nsect;		up->upwc = -(512 / sizeof (short));#ifdef UPECCDEBUG		printf("revector to cn %d tn %d sn %d\n", cn, tn, sn);#endif		break;	case CONT:#ifdef UPECCDEBUG		printf("upecc, CONT: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn);#endif		bp->b_flags &= ~B_BAD;		up->upwc = -((bp->b_bcount - (int)ptob(npf)) / sizeof(short));		if (up->upwc == 0)			return(0);		break;	}	if (up->upwc == 0) {		um->um_tab.b_active = 0;		return (0);	}	/*	 * Have to continue the transfer... clear the drive,	 * and compute the position where the transfer is to continue.	 * We have completed npf+1 sectors of the transfer already;	 * restart at offset o of next sector (i.e. in UBA register reg+1).	 */#ifdef notdef	up->uper1 = 0;	up->upcs1 |= UP_GO;#else	up->upcs1 = UP_TRE|UP_IE|UP_DCLR|UP_GO;	up->updc = cn;	up->upda = (tn << 8) | sn;	ubaddr = (int)ptob(reg) + o;	up->upba = ubaddr;	cmd = (ubaddr >> 8) & 0x300;	cmd |= ((bp->b_flags&B_READ)?UP_RCOM:UP_WCOM)|UP_IE|UP_GO;	um->um_tab.b_errcnt = 0;	up->upcs1 = cmd;#endif	return (1);}/* * Reset driver after UBA init. * Cancel software state of all pending transfers * and restart all units and the controller. */upreset(uban)	int uban;{	register struct uba_ctlr *um;	register struct uba_device *ui;	register sc21, unit;	for (sc21 = 0; sc21 < nNSC; sc21++) {		if ((um = upminfo[sc21]) == 0 || um->um_ubanum != uban ||		    um->um_alive == 0)			continue;		printf(" sc%d", sc21);		um->um_tab.b_active = 0;		um->um_tab.b_actf = um->um_tab.b_actl = 0;		up_softc[sc21].sc_recal = 0;		up_softc[sc21].sc_wticks = 0;		if (um->um_ubinfo) {			printf("<%d>", (um->um_ubinfo>>28)&0xf);			um->um_ubinfo = 0;		}		((struct updevice *)(um->um_addr))->upcs2 = UPCS2_CLR;		for (unit = 0; unit < nNUP; unit++) {			if ((ui = updinfo[unit]) == 0)				continue;			if (ui->ui_alive == 0 || ui->ui_mi != um)				continue;			uputab[unit].b_active = 0;			(void) upustart(ui);		}		(void) upstart(um);	}}/* * Wake up every second and if an interrupt is pending * but nothing has happened increment a counter. * If nothing happens for 20 seconds, reset the UNIBUS * and begin anew. */upwatch(){	register struct uba_ctlr *um;	register sc21, unit;	register struct up_softc *sc;	timeout(upwatch, (caddr_t)0, hz);	for (sc21 = 0; sc21 < nNSC; sc21++) {		um = upminfo[sc21];		if (um == 0 || um->um_alive == 0)			continue;		sc = &up_softc[sc21];		if (um->um_tab.b_active == 0) {			for (unit = 0; unit < nNUP; unit++)				if (uputab[unit].b_active &&				    updinfo[unit]->ui_mi == um)					goto active;			sc->sc_wticks = 0;			continue;		}active:		sc->sc_wticks++;		if (sc->sc_wticks >= 20) {			sc->sc_wticks = 0;			printf("sc%d: lost interrupt\n", sc21);			ubareset(um->um_ubanum);		}	}}#define	DBSIZE	20updump(dev, dumpinfo)	dev_t dev;			/* dump device */	struct dumpinfo dumpinfo;	/* dump info */{#ifdef notdef	struct updevice *upaddr;	char *start;	char *start_tmp;	int blk, unit, ubatype;	register struct uba_regs *uba;	register struct uba_device *ui;	register short *rp;	struct upst *st;	register int retry;	unit = minor(dev) >> 3;	if (unit >= nNUP)		return (ENXIO);#define	phys(cast, addr) ((cast)((int)addr & 0x7fffffff))	ui = phys(struct uba_device *, updinfo[unit]);	if (ui->ui_alive == 0)		return (ENXIO);	uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba;	ubatype = phys(struct uba_hd *, ui->ui_hd)->uba_type;	ubainit(uba,ubatype);	upaddr = (struct updevice *)ui->ui_physaddr;	DELAY(5000000);	upaddr->upcs2 = unit;	DELAY(100);	upaddr->upcs1 = UP_DCLR|UP_GO;	upaddr->upcs1 = UP_PRESET|UP_GO;	upaddr->upof = UPOF_FMT22;	retry = 0;	do {		DELAY(25);		if (++retry > 527)			break;	} while ((upaddr->upds & UP_RDY) == 0);	if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY)		return (EFAULT);	start = start_tmp = 0;	st = &upst[ui->ui_type];	/*	 * If a full dump is being performed, then this loop	 * will dump all of core. If a partial dump is being	 * performed, then as much of core as possible will be	 * dumped, leaving room for the u_area and error logger	 * buffer. Please note that dumpsys predetermined what	 * type of dump will be performed.	 */	while ((dumpinfo.size_to_dump > 0) || (dumpinfo.partial_dump)) {		register struct pte *io;		register int i;		int cn, sn, tn;		daddr_t bn;		blk = dumpinfo.size_to_dump > DBSIZE ? DBSIZE : dumpinfo.size_to_dump;		io = uba->uba_map;		for (i = 0; i < blk; i++)			*(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV;		*(int *)io = 0;		bn = dumplo + btop(start_tmp);		cn = bn/st->nspc + dumpinfo.blkoffs / st->nspc;		sn = bn%st->nspc;		tn = sn/st->nsect;		sn = sn%st->nsect;		upaddr->updc = cn;		rp = (short *) &upaddr->upda;		*rp = (tn << 8) + sn;		*--rp = 0;		*--rp = -blk*NBPG / sizeof (short);		*--rp = UP_GO|UP_WCOM;		retry = 0;		do {			DELAY(25);			if (++retry > 527)				break;		} while ((upaddr->upcs1 & UP_RDY) == 0);		if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY) {			printf("up%d: not ready", unit);			if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY) {				printf("\n");				return (EIO);			}			printf(" (flakey)\n");		}		if (upaddr->upds&UPDS_ERR)			return (EIO);		start += blk*NBPG;		start_tmp += blk*NBPG;		dumpinfo.size_to_dump -= blk;		if ((dumpinfo.size_to_dump <= 0) && (dumpinfo.partial_dump)) {						/*			 * If a partial dump is being performed....			 */			/* Set size_to_dump to the number of pages of elbuf */			dumpinfo.size_to_dump = 			  dumpinfo.pdump[NUM_TO_DUMP-dumpinfo.partial_dump].num_blks;			/* Set start to starting address */			start = 0;			start += 			  dumpinfo.pdump[NUM_TO_DUMP-dumpinfo.partial_dump].start_addr;			dumpinfo.partial_dump--;		}	}	return (0);#endif notdef}upsize(dev)	dev_t dev;{	int unit = minor(dev) >> 3;	struct uba_device *ui;	struct upst *st;	if (unit >= nNUP || (ui = updinfo[unit]) == 0 || ui->ui_alive == 0)		return (-1);	/*	 *	Sanity check		001	 */	if ( up_part[unit].pt_valid != PT_VALID )		panic("upsize: invalid partition table ");	return (up_part[unit].pt_part[minor(dev) & 07].pi_nblocks); /* 001 */}#endif

⌨️ 快捷键说明

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