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

📄 uda.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
	struct udadevice *udaddr;	struct uda1 *ud_ubaddr;	char *start;	int num, blk, unit, maxsz, blkoff, reg;	struct partition *pp;	register struct uba_regs *uba;	register struct uba_device *ui;	register struct uda1 *ud;	register struct pte *io;	register int i;	/*	 * Make sure the device is a reasonable place on which to dump.	 */	unit = udaunit(dev);	if (unit >= NRA)		return (ENXIO);#define	phys(cast, addr)	((cast) ((int)addr & 0x7fffffff))	ui = phys(struct uba_device *, udadinfo[unit]);	if (ui == NULL || ui->ui_alive == 0)		return (ENXIO);	/*	 * Find and initialise the UBA; get the physical address of the	 * device registers, and of communications area and command and	 * response packet.	 */	uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba;	ubainit(uba);	udaddr = (struct udadevice *)ui->ui_physaddr;	ud = phys(struct uda1 *, &uda1);	/*	 * Map the ca+packets into Unibus I/O space so the UDA50 can get	 * at them.  Use the registers at the end of the Unibus map (since	 * we will use the registers at the beginning to map the memory	 * we are dumping).	 */	num = btoc(sizeof(struct uda1)) + 1;	reg = NUBMREG - num;	io = &uba->uba_map[reg];	for (i = 0; i < num; i++)		*(int *)io++ = UBAMR_MRV | (btop(ud) + i);	ud_ubaddr = (struct uda1 *)(((int)ud & PGOFSET) | (reg << 9));	/*	 * Initialise the controller, with one command and one response	 * packet.	 */	udaddr->udaip = 0;	if (udadumpwait(udaddr, UDA_STEP1))		return (EFAULT);	udaddr->udasa = UDA_ERR;	if (udadumpwait(udaddr, UDA_STEP2))		return (EFAULT);	udaddr->udasa = (int)&ud_ubaddr->uda1_ca.ca_rspdsc;	if (udadumpwait(udaddr, UDA_STEP3))		return (EFAULT);	udaddr->udasa = ((int)&ud_ubaddr->uda1_ca.ca_rspdsc) >> 16;	if (udadumpwait(udaddr, UDA_STEP4))		return (EFAULT);	uda_softc[ui->ui_ctlr].sc_micro = udaddr->udasa & 0xff;	udaddr->udasa = UDA_GO;	/*	 * Set up the command and response descriptor, then set the	 * controller characteristics and bring the drive on line.	 * Note that all uninitialised locations in uda1_cmd are zero.	 */	ud->uda1_ca.ca_rspdsc = (long)&ud_ubaddr->uda1_rsp.mscp_cmdref;	ud->uda1_ca.ca_cmddsc = (long)&ud_ubaddr->uda1_cmd.mscp_cmdref;	/* ud->uda1_cmd.mscp_sccc.sccc_ctlrflags = 0; */	/* ud->uda1_cmd.mscp_sccc.sccc_version = 0; */	if (udadumpcmd(M_OP_SETCTLRC, ud, ui))		return (EFAULT);	ud->uda1_cmd.mscp_unit = ui->ui_slave;	if (udadumpcmd(M_OP_ONLINE, ud, ui))		return (EFAULT);	pp = phys(struct partition *,	    &udalabel[unit].d_partitions[udapart(dev)]);	maxsz = pp->p_size;	blkoff = pp->p_offset;	/*	 * Dump all of physical memory, or as much as will fit in the	 * space provided.	 */	start = 0;	num = maxfree;	if (dumplo + num >= maxsz)		num = maxsz - dumplo;	blkoff += dumplo;	/*	 * Write out memory, DBSIZE pages at a time.	 * N.B.: this code depends on the fact that the sector	 * size == the page size.	 */	while (num > 0) {		blk = num > DBSIZE ? DBSIZE : num;		io = uba->uba_map;		/*		 * Map in the pages to write, leaving an invalid entry		 * at the end to guard against wild Unibus transfers.		 * Then do the write.		 */		for (i = 0; i < blk; i++)			*(int *)io++ = UBAMR_MRV | (btop(start) + i);		*(int *)io = 0;		ud->uda1_cmd.mscp_unit = ui->ui_slave;		ud->uda1_cmd.mscp_seq.seq_lbn = btop(start) + blkoff;		ud->uda1_cmd.mscp_seq.seq_bytecount = blk << PGSHIFT;		if (udadumpcmd(M_OP_WRITE, ud, ui))			return (EIO);		start += blk << PGSHIFT;		num -= blk;	}	return (0);		/* made it! */}/* * Wait for some of the bits in `bits' to come on.  If the error bit * comes on, or ten seconds pass without response, return true (error). */udadumpwait(udaddr, bits)	register struct udadevice *udaddr;	register int bits;{	register int timo = todr() + 1000;	while ((udaddr->udasa & bits) == 0) {		if (udaddr->udasa & UDA_ERR) {			printf("udasa=%b\ndump ", udaddr->udasa, udasr_bits);			return (1);		}		if (todr() >= timo) {			printf("timeout\ndump ");			return (1);		}	}	return (0);}/* * Feed a command to the UDA50, wait for its response, and return * true iff something went wrong. */udadumpcmd(op, ud, ui)	int op;	register struct uda1 *ud;	struct uba_device *ui;{	register struct udadevice *udaddr;	register int n;#define mp (&ud->uda1_rsp)	udaddr = (struct udadevice *)ui->ui_physaddr;	ud->uda1_cmd.mscp_opcode = op;	ud->uda1_cmd.mscp_msglen = MSCP_MSGLEN;	ud->uda1_rsp.mscp_msglen = MSCP_MSGLEN;	ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT;	ud->uda1_ca.ca_cmddsc |= MSCP_OWN | MSCP_INT;	if (udaddr->udasa & UDA_ERR) {		printf("udasa=%b\ndump ", udaddr->udasa, udasr_bits);		return (1);	}	n = udaddr->udaip;	n = todr() + 1000;	for (;;) {		if (todr() > n) {			printf("timeout\ndump ");			return (1);		}		if (ud->uda1_ca.ca_cmdint)			ud->uda1_ca.ca_cmdint = 0;		if (ud->uda1_ca.ca_rspint == 0)			continue;		ud->uda1_ca.ca_rspint = 0;		if (mp->mscp_opcode == (op | M_OP_END))			break;		printf("\n");		switch (MSCP_MSGTYPE(mp->mscp_msgtc)) {		case MSCPT_SEQ:			printf("sequential");			break;		case MSCPT_DATAGRAM:			mscp_decodeerror("uda", ui->ui_ctlr, mp);			printf("datagram");			break;		case MSCPT_CREDITS:			printf("credits");			break;		case MSCPT_MAINTENANCE:			printf("maintenance");			break;		default:			printf("unknown (type 0x%x)",				MSCP_MSGTYPE(mp->mscp_msgtc));			break;		}		printf(" ignored\ndump ");		ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT;	}	if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {		printf("error: op 0x%x => 0x%x status 0x%x\ndump ", op,			mp->mscp_opcode, mp->mscp_status);		return (1);	}	return (0);#undef mp}/* * Return the size of a partition, if known, or -1 if not. */udasize(dev)	dev_t dev;{	register int unit = udaunit(dev);	register struct uba_device *ui;	if (unit >= NRA || (ui = udadinfo[unit]) == NULL ||	    ui->ui_alive == 0 || (ui->ui_flags & UNIT_ONLINE) == 0 ||	    ra_info[unit].ra_state != OPEN)		return (-1);	return ((int)udalabel[unit].d_partitions[udapart(dev)].p_size);}#ifdef COMPAT_42/* * Tables mapping unlabelled drives. */struct size {	daddr_t nblocks;	daddr_t blkoff;} ra60_sizes[8] = {	15884,	0,		/* A=sectors 0 thru 15883 */	33440,	15884,		/* B=sectors 15884 thru 49323 */	400176,	0,		/* C=sectors 0 thru 400175 */	82080,	49324,		/* 4.2 G => D=sectors 49324 thru 131403 */	268772,	131404,		/* 4.2 H => E=sectors 131404 thru 400175 */	350852,	49324,		/* F=sectors 49324 thru 400175 */	157570,	242606,		/* UCB G => G=sectors 242606 thru 400175 */	193282,	49324,		/* UCB H => H=sectors 49324 thru 242605 */}, ra70_sizes[8] = {	15884,	0,		/* A=blk 0 thru 15883 */	33440,	15972,		/* B=blk 15972 thru 49323 */	-1,	0,		/* C=blk 0 thru end */	15884,	341220,		/* D=blk 341220 thru 357103 */	55936,	357192,		/* E=blk 357192 thru 413127 */	-1,	413457,		/* F=blk 413457 thru end */	-1,	341220,		/* G=blk 341220 thru end */	291346,	49731,		/* H=blk 49731 thru 341076 */}, ra80_sizes[8] = {	15884,	0,		/* A=sectors 0 thru 15883 */	33440,	15884,		/* B=sectors 15884 thru 49323 */	242606,	0,		/* C=sectors 0 thru 242605 */	0,	0,		/* D=unused */	193282,	49324,		/* UCB H => E=sectors 49324 thru 242605 */	82080,	49324,		/* 4.2 G => F=sectors 49324 thru 131403 */	192696,	49910,		/* G=sectors 49910 thru 242605 */	111202,	131404,		/* 4.2 H => H=sectors 131404 thru 242605 */}, ra81_sizes[8] ={/* * These are the new standard partition sizes for ra81's. * An RA_COMPAT system is compiled with D, E, and F corresponding * to the 4.2 partitions for G, H, and F respectively. */#ifndef	UCBRA	15884,	0,		/* A=sectors 0 thru 15883 */	66880,	16422,		/* B=sectors 16422 thru 83301 */	891072,	0,		/* C=sectors 0 thru 891071 */#ifdef RA_COMPAT	82080,	49324,		/* 4.2 G => D=sectors 49324 thru 131403 */	759668,	131404,		/* 4.2 H => E=sectors 131404 thru 891071 */	478582,	412490,		/* 4.2 F => F=sectors 412490 thru 891071 */#else	15884,	375564,		/* D=sectors 375564 thru 391447 */	307200,	391986,		/* E=sectors 391986 thru 699185 */	191352,	699720,		/* F=sectors 699720 thru 891071 */#endif RA_COMPAT	515508,	375564,		/* G=sectors 375564 thru 891071 */	291346,	83538,		/* H=sectors 83538 thru 374883 *//* * These partitions correspond to the sizes used by sites at Berkeley, * and by those sites that have received copies of the Berkeley driver * with deltas 6.2 or greater (11/15/83). */#else UCBRA	15884,	0,		/* A=sectors 0 thru 15883 */	33440,	15884,		/* B=sectors 15884 thru 49323 */	891072,	0,		/* C=sectors 0 thru 891071 */	15884,	242606,		/* D=sectors 242606 thru 258489 */	307200,	258490,		/* E=sectors 258490 thru 565689 */	325382,	565690,		/* F=sectors 565690 thru 891071 */	648466,	242606,		/* G=sectors 242606 thru 891071 */	193282,	49324,		/* H=sectors 49324 thru 242605 */#endif UCBRA}, ra82_sizes[8] = {	15884,	0,		/* A=blk 0 thru 15883 */	66880,	16245,		/* B=blk 16245 thru 83124 */	-1,	0,		/* C=blk 0 thru end */	15884,	375345,		/* D=blk 375345 thru 391228 */	307200,	391590,		/* E=blk 391590 thru 698789 */	-1,	699390,		/* F=blk 699390 thru end */	-1,	375345,		/* G=blk 375345 thru end */	291346,	83790,		/* H=blk 83790 thru 375135 */}, rc25_sizes[8] = {	15884,	0,		/* A=blk 0 thru 15883 */	10032,	15884,		/* B=blk 15884 thru 49323 */	-1,	0,		/* C=blk 0 thru end */	0,	0,		/* D=blk 340670 thru 356553 */	0,	0,		/* E=blk 356554 thru 412489 */	0,	0,		/* F=blk 412490 thru end */	-1,	25916,		/* G=blk 49324 thru 131403 */	0,	0,		/* H=blk 131404 thru end */}, rd52_sizes[8] = {	15884,	0,		/* A=blk 0 thru 15883 */	9766,	15884,		/* B=blk 15884 thru 25649 */	-1,	0,		/* C=blk 0 thru end */	0,	0,		/* D=unused */	0,	0,		/* E=unused */	0,	0,		/* F=unused */	-1,	25650,		/* G=blk 25650 thru end */	0,	0,		/* H=unused */}, rd53_sizes[8] = {	15884,	0,		/* A=blk 0 thru 15883 */	33440,	15884,		/* B=blk 15884 thru 49323 */	-1,	0,		/* C=blk 0 thru end */	0,	0,		/* D=unused */	33440,	0,		/* E=blk 0 thru 33439 */	-1,	33440,		/* F=blk 33440 thru end */	-1,	49324,		/* G=blk 49324 thru end */	-1,	15884,		/* H=blk 15884 thru end */}, rd54_sizes[8] = {	15884,	0,		/* A=blk 0 thru 15883 */	33440,	15884,		/* B=blk 15884 thru 49323 */	-1,	0,		/* C=blk 0 thru end */	130938,	49324,		/* D=blk 49324 thru 180261 */	130938,	180262,		/* E=blk 180262 thru 311199 (end) */	0,	0,		/* F=unused */	261876,	49324,		/* G=blk 49324 thru 311199 (end) */	0,	0,		/* H=unused */}, rx50_sizes[8] = {	800,	0,		/* A=blk 0 thru 799 */	0,	0,	-1,	0,		/* C=blk 0 thru end */	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,};/* * Media ID decoding table. */struct	udatypes {	u_long	ut_id;		/* media drive ID */	char	*ut_name;	/* drive type name */	struct	size *ut_sizes;	/* partition tables */	int	ut_nsectors, ut_ntracks, ut_ncylinders;} udatypes[] = {	{ MSCP_MKDRIVE2('R', 'A', 60), "ra60", ra60_sizes, 42, 4, 2382 },	{ MSCP_MKDRIVE2('R', 'A', 70), "ra70", ra70_sizes, 33, 11, 1507 },	{ MSCP_MKDRIVE2('R', 'A', 80), "ra80", ra80_sizes, 31, 14, 559 },	{ MSCP_MKDRIVE2('R', 'A', 81), "ra81", ra81_sizes, 51, 14, 1248 },	{ MSCP_MKDRIVE2('R', 'A', 82), "ra82", ra82_sizes, 57, 15, 1423 },	{ MSCP_MKDRIVE2('R', 'C', 25), "rc25-removable",						rc25_sizes, 42, 4, 302 },	{ MSCP_MKDRIVE3('R', 'C', 'F', 25), "rc25-fixed",						rc25_sizes, 42, 4, 302 },	{ MSCP_MKDRIVE2('R', 'D', 52), "rd52", rd52_sizes, 18, 7, 480 },	{ MSCP_MKDRIVE2('R', 'D', 53), "rd53", rd53_sizes, 18, 8, 963 },	{ MSCP_MKDRIVE2('R', 'D', 32), "rd54-from-rd32",						rd54_sizes, 17, 15, 1220 },	{ MSCP_MKDRIVE2('R', 'D', 54), "rd54", rd54_sizes, 17, 15, 1220 },	{ MSCP_MKDRIVE2('R', 'X', 50), "rx50", rx50_sizes, 10, 1, 80 },	0};#define NTYPES (sizeof(udatypes) / sizeof(*udatypes))udamaptype(unit, lp)	int unit;	register struct disklabel *lp;{	register struct udatypes *ut;	register struct size *sz;	register struct partition *pp;	register char *p;	register int i;	register struct ra_info *ra = &ra_info[unit];	i = MSCP_MEDIA_DRIVE(ra->ra_mediaid);	for (ut = udatypes; ut->ut_id; ut++)		if (ut->ut_id == i &&		    ut->ut_nsectors == ra->ra_geom.rg_nsectors &&		    ut->ut_ntracks == ra->ra_geom.rg_ntracks &&		    ut->ut_ncylinders == ra->ra_geom.rg_ncyl)			goto found;	/* not one we know; fake up a label for the whole drive */	uda_makefakelabel(ra, lp);	i = ra->ra_mediaid;	/* print the port type too */	addlog(": no partition table for %c%c %c%c%c%d, size %d;\n\using (s,t,c)=(%d,%d,%d)",		MSCP_MID_CHAR(4, i), MSCP_MID_CHAR(3, i),		MSCP_MID_CHAR(2, i), MSCP_MID_CHAR(1, i),		MSCP_MID_CHAR(0, i), MSCP_MID_NUM(i), lp->d_secperunit,		lp->d_nsectors, lp->d_ntracks, lp->d_ncylinders);	if (!cold)		addlog("\n");	return (0);found:	p = ut->ut_name;	for (i = 0; i < sizeof(lp->d_typename) - 1 && *p; i++)		lp->d_typename[i] = *p++;	lp->d_typename[i] = 0;	sz = ut->ut_sizes;	lp->d_nsectors = ut->ut_nsectors;	lp->d_ntracks = ut->ut_ntracks;	lp->d_ncylinders = ut->ut_ncylinders;	lp->d_npartitions = 8;	lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;	for (pp = lp->d_partitions; pp < &lp->d_partitions[8]; pp++, sz++) {		pp->p_offset = sz->blkoff;		if ((pp->p_size = sz->nblocks) == (u_long)-1)			pp->p_size = ra->ra_dsize - sz->blkoff;	}	return (1);}#endif /* COMPAT_42 *//* * Construct a label for a drive from geometry information * if we have no better information. */uda_makefakelabel(ra, lp)	register struct ra_info *ra;	register struct disklabel *lp;{	lp->d_nsectors = ra->ra_geom.rg_nsectors;	lp->d_ntracks = ra->ra_geom.rg_ntracks;	lp->d_ncylinders = ra->ra_geom.rg_ncyl;	lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;	bcopy("ra??", lp->d_typename, sizeof("ra??"));	lp->d_npartitions = 1;	lp->d_partitions[0].p_offset = 0;	lp->d_partitions[0].p_size = lp->d_secperunit;}#endif /* NUDA > 0 */

⌨️ 快捷键说明

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