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

📄 rd.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	register int unit;{	register struct buf *bp;	register struct rd_softc *rs = &rd_softc[unit];	bp = rdtab[unit].b_actf;	rs->sc_addr = bp->b_un.b_addr;	rs->sc_resid = bp->b_bcount;	if (hpibreq(&rs->sc_dq))		rdstart(unit);}struct buf *rdfinish(unit, rs, bp)	int unit;	register struct rd_softc *rs;	register struct buf *bp;{	register struct buf *dp = &rdtab[unit];	dp->b_errcnt = 0;	dp->b_actf = bp->b_actf;	bp->b_resid = 0;	biodone(bp);	hpibfree(&rs->sc_dq);	if (dp->b_actf)		return(dp->b_actf);	dp->b_active = 0;	if (rs->sc_flags & RDF_WANTED) {		rs->sc_flags &= ~RDF_WANTED;		wakeup((caddr_t)dp);	}	return(NULL);}rdstart(unit)	register int unit;{	register struct rd_softc *rs = &rd_softc[unit];	register struct buf *bp = rdtab[unit].b_actf;	register struct hp_device *hp = rs->sc_hd;	register int part;again:#ifdef DEBUG	if (rddebug & RDB_FOLLOW)		printf("rdstart(%d): bp %x, %c\n", unit, bp,		       (bp->b_flags & B_READ) ? 'R' : 'W');#endif	part = rdpart(bp->b_dev);	rs->sc_flags |= RDF_SEEK;	rs->sc_ioc.c_unit = C_SUNIT(rs->sc_punit);	rs->sc_ioc.c_volume = C_SVOL(0);	rs->sc_ioc.c_saddr = C_SADDR;	rs->sc_ioc.c_hiaddr = 0;	rs->sc_ioc.c_addr = RDBTOS(bp->b_cylin);	rs->sc_ioc.c_nop2 = C_NOP;	rs->sc_ioc.c_slen = C_SLEN;	rs->sc_ioc.c_len = rs->sc_resid;	rs->sc_ioc.c_cmd = bp->b_flags & B_READ ? C_READ : C_WRITE;#ifdef DEBUG	if (rddebug & RDB_IO)		printf("rdstart: hpibsend(%x, %x, %x, %x, %x)\n",		       hp->hp_ctlr, hp->hp_slave, C_CMD,		       &rs->sc_ioc.c_unit, sizeof(rs->sc_ioc)-2);#endif	if (hpibsend(hp->hp_ctlr, hp->hp_slave, C_CMD, &rs->sc_ioc.c_unit,		     sizeof(rs->sc_ioc)-2) == sizeof(rs->sc_ioc)-2) {		if (hp->hp_dk >= 0) {			dk_busy |= 1 << hp->hp_dk;			dk_seek[hp->hp_dk]++;		}#ifdef DEBUG		if (rddebug & RDB_IO)			printf("rdstart: hpibawait(%x)\n", hp->hp_ctlr);#endif		hpibawait(hp->hp_ctlr);		return;	}	/*	 * Experience has shown that the hpibwait in this hpibsend will	 * occasionally timeout.  It appears to occur mostly on old 7914	 * drives with full maintenance tracks.  We should probably	 * integrate this with the backoff code in rderror.	 */#ifdef DEBUG	if (rddebug & RDB_ERROR)		printf("rd%d: rdstart: cmd %x adr %d blk %d len %d ecnt %d\n",		       unit, rs->sc_ioc.c_cmd, rs->sc_ioc.c_addr,		       bp->b_blkno, rs->sc_resid, rdtab[unit].b_errcnt);	rdstats[unit].rdretries++;#endif	rs->sc_flags &= ~RDF_SEEK;	rdreset(rs, hp);	if (rdtab[unit].b_errcnt++ < RDRETRY)		goto again;	printf("rd%d: rdstart err: cmd 0x%x sect %d blk %d len %d\n",	       unit, rs->sc_ioc.c_cmd, rs->sc_ioc.c_addr,	       bp->b_blkno, rs->sc_resid);	bp->b_flags |= B_ERROR;	bp->b_error = EIO;	bp = rdfinish(unit, rs, bp);	if (bp) {		rs->sc_addr = bp->b_un.b_addr;		rs->sc_resid = bp->b_bcount;		if (hpibreq(&rs->sc_dq))			goto again;	}}rdgo(unit)	register int unit;{	register struct rd_softc *rs = &rd_softc[unit];	register struct hp_device *hp = rs->sc_hd;	struct buf *bp = rdtab[unit].b_actf;	if (hp->hp_dk >= 0) {		dk_busy |= 1 << hp->hp_dk;		dk_xfer[hp->hp_dk]++;		dk_wds[hp->hp_dk] += rs->sc_resid >> 6;	}#ifdef USELEDS	if (inledcontrol == 0)		ledcontrol(0, 0, LED_DISK);#endif	hpibgo(hp->hp_ctlr, hp->hp_slave, C_EXEC,	       rs->sc_addr, rs->sc_resid, bp->b_flags & B_READ);}rdintr(unit)	register int unit;{	register struct rd_softc *rs = &rd_softc[unit];	register struct buf *bp = rdtab[unit].b_actf;	register struct hp_device *hp = rs->sc_hd;	u_char stat = 13;	/* in case hpibrecv fails */	int rv, restart;	#ifdef DEBUG	if (rddebug & RDB_FOLLOW)		printf("rdintr(%d): bp %x, %c, flags %x\n", unit, bp,		       (bp->b_flags & B_READ) ? 'R' : 'W', rs->sc_flags);	if (bp == NULL) {		printf("rd%d: bp == NULL\n", unit);		return;	}#endif	if (hp->hp_dk >= 0)		dk_busy &= ~(1 << hp->hp_dk);	if (rs->sc_flags & RDF_SEEK) {		rs->sc_flags &= ~RDF_SEEK;		if (hpibustart(hp->hp_ctlr))			rdgo(unit);		return;	}	if ((rs->sc_flags & RDF_SWAIT) == 0) {#ifdef DEBUG		rdstats[unit].rdpolltries++;#endif		if (hpibpptest(hp->hp_ctlr, hp->hp_slave) == 0) {#ifdef DEBUG			rdstats[unit].rdpollwaits++;#endif			if (hp->hp_dk >= 0)				dk_busy |= 1 << hp->hp_dk;			rs->sc_flags |= RDF_SWAIT;			hpibawait(hp->hp_ctlr);			return;		}	} else		rs->sc_flags &= ~RDF_SWAIT;	rv = hpibrecv(hp->hp_ctlr, hp->hp_slave, C_QSTAT, &stat, 1);	if (rv != 1 || stat) {#ifdef DEBUG		if (rddebug & RDB_ERROR)			printf("rdintr: recv failed or bad stat %d\n", stat);#endif		restart = rderror(unit);#ifdef DEBUG		rdstats[unit].rdretries++;#endif		if (rdtab[unit].b_errcnt++ < RDRETRY) {			if (restart)				rdstart(unit);			return;		}		bp->b_flags |= B_ERROR;		bp->b_error = EIO;	}	if (rdfinish(unit, rs, bp))		rdustart(unit);}rdstatus(rs)	register struct rd_softc *rs;{	register int c, s;	u_char stat;	int rv;	c = rs->sc_hd->hp_ctlr;	s = rs->sc_hd->hp_slave;	rs->sc_rsc.c_unit = C_SUNIT(rs->sc_punit);	rs->sc_rsc.c_sram = C_SRAM;	rs->sc_rsc.c_ram = C_RAM;	rs->sc_rsc.c_cmd = C_STATUS;	bzero((caddr_t)&rs->sc_stat, sizeof(rs->sc_stat));	rv = hpibsend(c, s, C_CMD, &rs->sc_rsc, sizeof(rs->sc_rsc));	if (rv != sizeof(rs->sc_rsc)) {#ifdef DEBUG		if (rddebug & RDB_STATUS)			printf("rdstatus: send C_CMD failed %d != %d\n",			       rv, sizeof(rs->sc_rsc));#endif		return(1);	}	rv = hpibrecv(c, s, C_EXEC, &rs->sc_stat, sizeof(rs->sc_stat));	if (rv != sizeof(rs->sc_stat)) {#ifdef DEBUG		if (rddebug & RDB_STATUS)			printf("rdstatus: send C_EXEC failed %d != %d\n",			       rv, sizeof(rs->sc_stat));#endif		return(1);	}	rv = hpibrecv(c, s, C_QSTAT, &stat, 1);	if (rv != 1 || stat) {#ifdef DEBUG		if (rddebug & RDB_STATUS)			printf("rdstatus: recv failed %d or bad stat %d\n",			       rv, stat);#endif		return(1);	}	return(0);}/* * Deal with errors. * Returns 1 if request should be restarted, * 0 if we should just quietly give up. */rderror(unit)	int unit;{	struct rd_softc *rs = &rd_softc[unit];	register struct rd_stat *sp;	struct buf *bp;	daddr_t hwbn, pbn;	if (rdstatus(rs)) {#ifdef DEBUG		printf("rd%d: couldn't get status\n", unit);#endif		rdreset(rs, rs->sc_hd);		return(1);	}	sp = &rs->sc_stat;	if (sp->c_fef & FEF_REXMT)		return(1);	if (sp->c_fef & FEF_PF) {		rdreset(rs, rs->sc_hd);		return(1);	}	/*	 * Unit requests release for internal maintenance.	 * We just delay awhile and try again later.  Use expontially	 * increasing backoff ala ethernet drivers since we don't really	 * know how long the maintenance will take.  With RDWAITC and	 * RDRETRY as defined, the range is 1 to 32 seconds.	 */	if (sp->c_fef & FEF_IMR) {		extern int hz;		int rdtimo = RDWAITC << rdtab[unit].b_errcnt;#ifdef DEBUG		printf("rd%d: internal maintenance, %d second timeout\n",		       unit, rdtimo);		rdstats[unit].rdtimeouts++;#endif		hpibfree(&rs->sc_dq);		timeout(rdrestart, (void *)unit, rdtimo * hz);		return(0);	}	/*	 * Only report error if we have reached the error reporting	 * threshhold.  By default, this will only report after the	 * retry limit has been exceeded.	 */	if (rdtab[unit].b_errcnt < rderrthresh)		return(1);	/*	 * First conjure up the block number at which the error occured.	 * Note that not all errors report a block number, in that case	 * we just use b_blkno. 	 */	bp = rdtab[unit].b_actf;	pbn = rs->sc_info.ri_label.d_partitions[rdpart(bp->b_dev)].p_offset;	if ((sp->c_fef & FEF_CU) || (sp->c_fef & FEF_DR) ||	    (sp->c_ief & IEF_RRMASK)) {		hwbn = RDBTOS(pbn + bp->b_blkno);		pbn = bp->b_blkno;	} else {		hwbn = sp->c_blk;		pbn = RDSTOB(hwbn) - pbn;	}	/*	 * Now output a generic message suitable for badsect.	 * Note that we don't use harderr cuz it just prints	 * out b_blkno which is just the beginning block number	 * of the transfer, not necessary where the error occured.	 */	printf("rd%d%c: hard error sn%d\n",	       rdunit(bp->b_dev), 'a'+rdpart(bp->b_dev), pbn);	/*	 * Now report the status as returned by the hardware with	 * attempt at interpretation (unless debugging).	 */	printf("rd%d %s error:",	       unit, (bp->b_flags & B_READ) ? "read" : "write");#ifdef DEBUG	if (rddebug & RDB_ERROR) {		/* status info */		printf("\n    volume: %d, unit: %d\n",		       (sp->c_vu>>4)&0xF, sp->c_vu&0xF);		rdprinterr("reject", sp->c_ref, err_reject);		rdprinterr("fault", sp->c_fef, err_fault);		rdprinterr("access", sp->c_aef, err_access);		rdprinterr("info", sp->c_ief, err_info);		printf("    block: %d, P1-P10: ", hwbn);		printf("%s", hexstr(*(u_int *)&sp->c_raw[0], 8));		printf("%s", hexstr(*(u_int *)&sp->c_raw[4], 8));		printf("%s\n", hexstr(*(u_short *)&sp->c_raw[8], 4));		/* command */		printf("    ioc: ");		printf("%s", hexstr(*(u_int *)&rs->sc_ioc.c_pad, 8));		printf("%s", hexstr(*(u_short *)&rs->sc_ioc.c_hiaddr, 4));		printf("%s", hexstr(*(u_int *)&rs->sc_ioc.c_addr, 8));		printf("%s", hexstr(*(u_short *)&rs->sc_ioc.c_nop2, 4));		printf("%s", hexstr(*(u_int *)&rs->sc_ioc.c_len, 8));		printf("%s\n", hexstr(*(u_short *)&rs->sc_ioc.c_cmd, 4));		return(1);	}#endif	printf(" v%d u%d, R0x%x F0x%x A0x%x I0x%x\n",	       (sp->c_vu>>4)&0xF, sp->c_vu&0xF,	       sp->c_ref, sp->c_fef, sp->c_aef, sp->c_ief);	printf("P1-P10: ");	printf("%s", hexstr(*(u_int *)&sp->c_raw[0], 8));	printf("%s", hexstr(*(u_int *)&sp->c_raw[4], 8));	printf("%s\n", hexstr(*(u_short *)&sp->c_raw[8], 4));	return(1);}intrdread(dev, uio, flags)	dev_t dev;	struct uio *uio;	int flags;{	return (physio(rdstrategy, NULL, dev, B_READ, minphys, uio));}intrdwrite(dev, uio, flags)	dev_t dev;	struct uio *uio;	int flags;{	return (physio(rdstrategy, NULL, dev, B_WRITE, minphys, uio));}intrdioctl(dev, cmd, data, flag, p)	dev_t dev;	int cmd;	caddr_t data;	int flag;	struct proc *p;{	int unit = rdunit(dev);	register struct rd_softc *sc = &rd_softc[unit];	register struct disklabel *lp = &sc->sc_info.ri_label;	int error, flags;	switch (cmd) {	case DIOCGDINFO:		*(struct disklabel *)data = *lp;		return (0);	case DIOCGPART:		((struct partinfo *)data)->disklab = lp;		((struct partinfo *)data)->part =			&lp->d_partitions[rdpart(dev)];		return (0);        case DIOCWLABEL:                if ((flag & FWRITE) == 0)                        return (EBADF);		if (*(int *)data)			sc->sc_flags |= RDF_WLABEL;		else			sc->sc_flags &= ~RDF_WLABEL;		return (0);        case DIOCSDINFO:                if ((flag & FWRITE) == 0)                        return (EBADF);		return (setdisklabel(lp, (struct disklabel *)data,				     (sc->sc_flags & RDF_WLABEL) ? 0				     : sc->sc_info.ri_open));        case DIOCWDINFO:		if ((flag & FWRITE) == 0)			return (EBADF);		error = setdisklabel(lp, (struct disklabel *)data,				     (sc->sc_flags & RDF_WLABEL) ? 0				     : sc->sc_info.ri_open);		if (error)			return (error);		flags = sc->sc_flags;		sc->sc_flags = RDF_ALIVE | RDF_WLABEL;		error = writedisklabel(rdlabdev(dev), rdstrategy, lp);		sc->sc_flags = flags;		return (error);	}	return(EINVAL);}intrdsize(dev)	dev_t dev;{	register int unit = rdunit(dev);	register struct rd_softc *rs = &rd_softc[unit];	int psize, didopen = 0;	if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0)		return(-1);	/*	 * We get called very early on (via swapconf)	 * without the device being open so we may need	 * to handle it here.	 */	if (rs->sc_info.ri_open == 0) {		if (rdopen(dev, FREAD|FWRITE, S_IFBLK, NULL))			return(-1);		didopen = 1;	}	psize = rs->sc_info.ri_label.d_partitions[rdpart(dev)].p_size;	if (didopen)		(void) rdclose(dev, FREAD|FWRITE, S_IFBLK, NULL);	return (psize);}#ifdef DEBUGrdprinterr(str, err, tab)	char *str;	short err;	char *tab[];{	register int i;	int printed;	if (err == 0)		return;	printf("    %s error field:", str, err);	printed = 0;	for (i = 0; i < 16; i++)		if (err & (0x8000 >> i))			printf("%s%s", printed++ ? " + " : " ", tab[i]);	printf("\n");}#endif/* * Non-interrupt driven, non-dma dump routine. */intrddump(dev)	dev_t dev;{	int part = rdpart(dev);	int unit = rdunit(dev);	register struct rd_softc *rs = &rd_softc[unit];	register struct hp_device *hp = rs->sc_hd;	register struct partition *pinfo;	register daddr_t baddr;	register int maddr, pages, i;	char stat;	extern int lowram, dumpsize;#ifdef DEBUG	extern int pmapdebug;	pmapdebug = 0;#endif	/* is drive ok? */	if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0)		return (ENXIO);	pinfo = &rs->sc_info.ri_label.d_partitions[part];	/* dump parameters in range? */	if (dumplo < 0 || dumplo >= pinfo->p_size ||	    pinfo->p_fstype != FS_SWAP)		return (EINVAL);	pages = dumpsize;	if (dumplo + ctod(pages) > pinfo->p_size)		pages = dtoc(pinfo->p_size - dumplo);	maddr = lowram;	baddr = dumplo + pinfo->p_offset;	/* HPIB idle? */	if (!hpibreq(&rs->sc_dq)) {		hpibreset(hp->hp_ctlr);		rdreset(rs, rs->sc_hd);		printf("[ drive %d reset ] ", unit);	}	for (i = 0; i < pages; i++) {#define NPGMB	(1024*1024/NBPG)		/* print out how many Mbs we have dumped */		if (i && (i % NPGMB) == 0)			printf("%d ", i / NPGMB);#undef NPBMG		rs->sc_ioc.c_unit = C_SUNIT(rs->sc_punit);		rs->sc_ioc.c_volume = C_SVOL(0);		rs->sc_ioc.c_saddr = C_SADDR;		rs->sc_ioc.c_hiaddr = 0;		rs->sc_ioc.c_addr = RDBTOS(baddr);		rs->sc_ioc.c_nop2 = C_NOP;		rs->sc_ioc.c_slen = C_SLEN;		rs->sc_ioc.c_len = NBPG;		rs->sc_ioc.c_cmd = C_WRITE;		hpibsend(hp->hp_ctlr, hp->hp_slave, C_CMD,			 &rs->sc_ioc.c_unit, sizeof(rs->sc_ioc)-2);		if (hpibswait(hp->hp_ctlr, hp->hp_slave))			return (EIO);		pmap_enter(kernel_pmap, (vm_offset_t)vmmap, maddr,		    VM_PROT_READ, TRUE);		hpibsend(hp->hp_ctlr, hp->hp_slave, C_EXEC, vmmap, NBPG);		(void) hpibswait(hp->hp_ctlr, hp->hp_slave);		hpibrecv(hp->hp_ctlr, hp->hp_slave, C_QSTAT, &stat, 1);		if (stat)			return (EIO);		maddr += NBPG;		baddr += ctod(1);	}	return (0);}#endif

⌨️ 快捷键说明

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