示例#1
0
文件: ow.c 项目: hmatyschok/MeshBSD
static int
ow_enumerate(device_t dev, ow_enum_fn *enumfp, ow_found_fn *foundfp)
{
	device_t lldev = device_get_parent(dev);
	int first, second, i, dir, prior, last, err, retries;
	uint64_t probed, last_mask;
	int sanity = 10;

	prior = -1;
	last_mask = 0;
	retries = 0;
	last = -2;
	err = ow_acquire_bus(dev, dev, OWN_DONTWAIT);
	if (err != 0)
		return err;
	while (last != -1) {
		if (sanity-- < 0) {
			printf("Reached the sanity limit\n");
			return EIO;
		}
again:
		probed = 0;
		last = -1;

		/*
		 * See AN397 section 5.II.C.3 for the algorithm (though a bit
		 * poorly stated). The search command forces each device to
		 * send ROM ID bits one at a time (first the bit, then the
		 * complement) the master (us) sends back a bit. If the
		 * device's bit doesn't match what we send back, that device
		 * stops sending bits back. So each time through we remember
		 * where we made the last decision (always 0). If there's a
		 * conflict there this time (and there will be in the absence
		 * of a hardware failure) we go with 1. This way, we prune the
		 * devices on the bus and wind up with a unique ROM. We know
		 * we're done when we detect no new conflicts. The same
		 * algorithm is used for devices in alarm state as well.
		 *
		 * In addition, experience has shown that sometimes devices
		 * stop responding in the middle of enumeration, so try this
		 * step again a few times when that happens. It is unclear if
		 * this is due to a nosiy electrical environment or some odd
		 * timing issue.
		 */

		/*
		 * The enumeration command should be successfully sent, if not,
		 * we have big issues on the bus so punt. Lower layers report
		 * any unusual errors, so we don't need to here.
		 */
		err = enumfp(dev, dev);
		if (err != 0)
			return (err);

		for (i = 0; i < 64; i++) {
			OWLL_READ_DATA(lldev, &timing_regular, &first);
			OWLL_READ_DATA(lldev, &timing_regular, &second);
			switch (first | second << 1) {
			case 0: /* Conflict */
				if (i < prior)
					dir = (last_mask >> i) & 1;
				else
					dir = i == prior;

				if (dir == 0)
					last = i;
				break;
			case 1: /* 1 then 0 -> 1 for all */
				dir = 1;
				break;
			case 2: /* 0 then 1 -> 0 for all */
				dir = 0;
				break;
			case 3:
				/*
				 * No device responded. This is unexpected, but
				 * experience has shown that on some platforms
				 * we miss a timing window, or otherwise have
				 * an issue. Start this step over. Since we've
				 * not updated prior yet, we can just jump to
				 * the top of the loop for a re-do of this step.
				 */
				printf("oops, starting over\n");
				if (++retries > 5)
					return (EIO);
				goto again;
			default: /* NOTREACHED */
				__unreachable();
			}
			if (dir) {
				OWLL_WRITE_ONE(lldev, &timing_regular);
				probed |= 1ull << i;
			} else {
				OWLL_WRITE_ZERO(lldev, &timing_regular);
			}
		}
		retries = 0;
		foundfp(dev, probed);
		last_mask = probed;
		prior = last;
	}
示例#2
0
/*
 * Like fgets, but go through the chain of compilation units chaining them
 * together.  Empty strings and files are ignored.
 */
char *
cu_fgets(char *buf, int n, int *more)
{
	static enum {ST_EOF, ST_FILE, ST_STRING} state = ST_EOF;
	static FILE *f;		/* Current open file */
	static char *s;		/* Current pointer inside string */
	static char string_ident[30];
	char *p;

again:
	switch (state) {
	case ST_EOF:
		if (script == NULL) {
			if (more != NULL)
				*more = 0;
			return (NULL);
		}
		linenum = 0;
		switch (script->type) {
		case CU_FILE:
			if ((f = fopen(script->s, "r")) == NULL)
				err(1, "%s", script->s);
			fname = script->s;
			state = ST_FILE;
			goto again;
		case CU_STRING:
			if (((size_t)snprintf(string_ident,
			    sizeof(string_ident), "\"%s\"", script->s)) >=
			    sizeof(string_ident) - 1)
				(void)strcpy(string_ident +
				    sizeof(string_ident) - 6, " ...\"");
			fname = string_ident;
			s = script->s;
			state = ST_STRING;
			goto again;
		default:
			__unreachable();
		}
	case ST_FILE:
		if ((p = fgets(buf, n, f)) != NULL) {
			linenum++;
			if (linenum == 1 && buf[0] == '#' && buf[1] == 'n')
				nflag = 1;
			if (more != NULL)
				*more = !feof(f);
			return (p);
		}
		script = script->next;
		(void)fclose(f);
		state = ST_EOF;
		goto again;
	case ST_STRING:
		if (linenum == 0 && s[0] == '#' && s[1] == 'n')
			nflag = 1;
		p = buf;
		for (;;) {
			if (n-- <= 1) {
				*p = '\0';
				linenum++;
				if (more != NULL)
					*more = 1;
				return (buf);
			}
			switch (*s) {
			case '\0':
				state = ST_EOF;
				if (s == script->s) {
					script = script->next;
					goto again;
				} else {
					script = script->next;
					*p = '\0';
					linenum++;
					if (more != NULL)
						*more = 0;
					return (buf);
				}
			case '\n':
				*p++ = '\n';
				*p = '\0';
				s++;
				linenum++;
				if (more != NULL)
					*more = 0;
				return (buf);
			default:
				*p++ = *s++;
			}
		}
	}
	/* NOTREACHED */
	return (NULL);
}