示例#1
0
文件: pcfclock.c 项目: MarginC/kame
static int 
pcfclock_read_dev(dev_t dev, char *buf, int maxretries) 
{
	u_int unit = minor(dev);
	device_t ppidev = UNITODEVICE(unit);
        device_t ppbus = device_get_parent(ppidev);
	int error = 0;

	ppb_set_mode(ppbus, PPB_COMPATIBLE);

	while (--maxretries > 0) {
		pcfclock_write_cmd(dev, PCFCLOCK_CMD_TIME);
		if (pcfclock_read_data(dev, buf, 68))
			continue;
			
		if (!PCFCLOCK_CORRECT_SYNC(buf))
			continue;

		if (!PCFCLOCK_CORRECT_FORMAT(buf))
			continue;

		break;
	}

	if (!maxretries)
		error = EIO;
	
	return (error);
}
示例#2
0
/*
 * ppb_1284_terminate()
 *
 * IEEE1284 termination phase, return code should ignored since the host
 * is _always_ in compatible mode after ppb_1284_terminate()
 */
int
ppb_1284_terminate(device_t bus)
{

#ifdef DEBUG_1284
	printf("T");
#endif

	/* do not reset error here to keep the error that
	 * may occured before the ppb_1284_terminate() call */
	ppb_1284_set_state(bus, PPB_TERMINATION);

#ifdef PERIPH_1284
	/* request remote host attention */
	ppb_wctr(bus, (nINIT | STROBE | SELECTIN) & ~(AUTOFEED));
	DELAY(1);
#endif /* PERIPH_1284 */

	/* Event 22 - set nSelectin low and nAutoFeed high */
	ppb_wctr(bus, (nINIT | SELECTIN) & ~(STROBE | AUTOFEED));

	/* Event 24 - waiting for peripheral, Xflag ignored */
	if (do_1284_wait(bus, nACK | nBUSY | nFAULT, nFAULT)) {
		ppb_1284_set_error(bus, PPB_TIMEOUT, 24);
		goto error;
	}

	/* Event 25 - set nAutoFd low */
	ppb_wctr(bus, (nINIT | SELECTIN | AUTOFEED) & ~STROBE);

	/* Event 26 - compatible mode status is set */

	/* Event 27 - peripheral set nAck high */
	if (do_1284_wait(bus, nACK, nACK)) {
		ppb_1284_set_error(bus, PPB_TIMEOUT, 27);
	}

	/* Event 28 - end termination, return to idle phase */
	ppb_wctr(bus, (nINIT | SELECTIN) & ~(STROBE | AUTOFEED));

error:
	/* return to compatible mode */
	ppb_set_mode(bus, PPB_COMPATIBLE);
	ppb_1284_set_state(bus, PPB_FORWARD_IDLE);

	return (0);
}
示例#3
0
/*
 * ppb_peripheral_terminate()
 *
 * Terminate peripheral transfer side
 *
 * Always return 0 in compatible mode
 */
int
ppb_peripheral_terminate(device_t bus, int how)
{
	int error = 0;

#ifdef DEBUG_1284
	printf("t");
#endif

	ppb_1284_set_state(bus, PPB_PERIPHERAL_TERMINATION);

	/* Event 22 - wait up to host response time (1s) */
	if ((error = do_peripheral_wait(bus, SELECT | nBUSY, 0))) {
		ppb_1284_set_error(bus, PPB_TIMEOUT, 22);
		goto error;
	}

	/* Event 24 */
	ppb_wctr(bus, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN));

	/* Event 25 - wait up to host response time (1s) */
	if ((error = do_peripheral_wait(bus, nBUSY, nBUSY))) {
		ppb_1284_set_error(bus, PPB_TIMEOUT, 25);
		goto error;
	}

	/* Event 26 */
	ppb_wctr(bus, (SELECTIN | nINIT | STROBE) & ~(AUTOFEED));
	DELAY(1);
	/* Event 27 */
	ppb_wctr(bus, (SELECTIN | nINIT) & ~(STROBE | AUTOFEED));

	/* Event 28 - wait up to host response time (1s) */
	if ((error = do_peripheral_wait(bus, nBUSY, 0))) {
		ppb_1284_set_error(bus, PPB_TIMEOUT, 28);
		goto error;
	}

error:
	ppb_set_mode(bus, PPB_COMPATIBLE);
	ppb_1284_set_state(bus, PPB_FORWARD_IDLE);

	return (0);
}
示例#4
0
/*
 * vpoio_detect()
 *
 * Detect and initialise the VP0 adapter.
 */
static int
vpoio_detect(struct vpoio_data *vpo)
{
	device_t ppbus = device_get_parent(vpo->vpo_dev);
	int error, ret;

	/* allocate the bus, then apply microsequences */
	if ((error = ppb_request_bus(ppbus, vpo->vpo_dev, PPB_DONTWAIT)))
		return (error);

	/* Force disconnection */
	ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq, &ret);

	/* Try to enter EPP mode, then connect to the drive in EPP mode */
	if (ppb_set_mode(ppbus, PPB_EPP) != -1) {
		/* call manually the microseq instead of using the appropriate function
		 * since we already requested the ppbus */
		ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_epp_microseq, &ret);
	}

	/* If EPP mode switch failed or ZIP connection in EPP mode failed,
	 * try to connect in NIBBLE mode */
	if (!vpoio_in_disk_mode(vpo)) {

		/* The interface must be at least PS/2 or NIBBLE capable.
		 * There is no way to know if the ZIP will work with
		 * PS/2 mode since PS/2 and SPP both use the same connect
		 * sequence. One must supress PS/2 with boot flags if
		 * PS/2 mode fails (see ppc(4)).
		 */
		if (ppb_set_mode(ppbus, PPB_PS2) != -1) {
			vpo->vpo_mode_found = VP0_MODE_PS2;
		} else {
			if (ppb_set_mode(ppbus, PPB_NIBBLE) == -1)
				goto error;

			vpo->vpo_mode_found = VP0_MODE_NIBBLE;
		}

		/* Can't know if the interface is capable of PS/2 yet */
		ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_spp_microseq, &ret);
		if (!vpoio_in_disk_mode(vpo)) {
			vpo->vpo_mode_found = VP0_MODE_UNDEFINED;
			if (bootverbose)
				device_printf(vpo->vpo_dev,
				    "can't connect to the drive\n");

			/* disconnect and release the bus */
			ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq,
					&ret);
			goto error;
		}
	} else {
		vpo->vpo_mode_found = VP0_MODE_EPP;
	}

	/* send SCSI reset signal */
	vpoio_reset(vpo);

	ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq, &ret);

	/* ensure we are disconnected or daisy chained peripheral
	 * may cause serious problem to the disk */
	if (vpoio_in_disk_mode(vpo)) {
		if (bootverbose)
			device_printf(vpo->vpo_dev,
			    "can't disconnect from the drive\n");
		goto error;
	}

	ppb_release_bus(ppbus, vpo->vpo_dev);
	return (0);

error:
	ppb_release_bus(ppbus, vpo->vpo_dev);
	return (VP0_EINITFAILED);
}
示例#5
0
/*
 * ppb_1284_negociate()
 *
 * IEEE1284 negociation phase
 *
 * Normal nibble mode or request device id mode (see ppb_1284.h)
 *
 * After negociation, nFAULT is low if data is available
 */
int
ppb_1284_negociate(device_t bus, int mode, int options)
{
	int error;
	int request_mode;

#ifdef DEBUG_1284
	printf("n");
#endif

	if (ppb_1284_get_state(bus) >= PPB_PERIPHERAL_NEGOCIATION)
		ppb_peripheral_terminate(bus, PPB_WAIT);

	if (ppb_1284_get_state(bus) != PPB_FORWARD_IDLE)
		ppb_1284_terminate(bus);

#ifdef DEBUG_1284
	printf("%d", mode);
#endif

	/* ensure the host is in compatible mode */
	ppb_set_mode(bus, PPB_COMPATIBLE);

	/* reset error to catch the actual negociation error */
	ppb_1284_reset_error(bus, PPB_FORWARD_IDLE);

	/* calculate ext. value */
	request_mode = ppb_request_mode(mode, options);

	/* default state */
	ppb_wctr(bus, (nINIT | SELECTIN) & ~(STROBE | AUTOFEED));
	DELAY(1);

	/* enter negociation phase */
	ppb_1284_set_state(bus, PPB_NEGOCIATION);

	/* Event 0 - put the exten. value on the data lines */
	ppb_wdtr(bus, request_mode);

#ifdef PERIPH_1284
	/* request remote host attention */
	ppb_wctr(bus, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN));
	DELAY(1);
	ppb_wctr(bus, (nINIT) & ~(STROBE | AUTOFEED | SELECTIN));
#else
	DELAY(1);

#endif /* !PERIPH_1284 */

	/* Event 1 - enter IEEE1284 mode */
	ppb_wctr(bus, (nINIT | AUTOFEED) & ~(STROBE | SELECTIN));

#ifdef PERIPH_1284
	/* ignore the PError line, wait a bit more, remote host's
	 * interrupts don't respond fast enough */
	if (ppb_poll_bus(bus, 40, nACK | SELECT | nFAULT,
				SELECT | nFAULT, PPB_NOINTR | PPB_POLL)) {
		ppb_1284_set_error(bus, PPB_NOT_IEEE1284, 2);
		error = ENODEV;
		goto error;
	}
#else
	/* Event 2 - trying IEEE1284 dialog */
	if (do_1284_wait(bus, nACK | PERROR | SELECT | nFAULT,
			PERROR  | SELECT | nFAULT)) {
		ppb_1284_set_error(bus, PPB_NOT_IEEE1284, 2);
		error = ENODEV;
		goto error;
	}
#endif /* !PERIPH_1284 */

	/* Event 3 - latch the ext. value to the peripheral */
	ppb_wctr(bus, (nINIT | STROBE | AUTOFEED) & ~SELECTIN);
	DELAY(1);

	/* Event 4 - IEEE1284 device recognized */
	ppb_wctr(bus, nINIT & ~(SELECTIN | AUTOFEED | STROBE));

	/* Event 6 - waiting for status lines */
	if (do_1284_wait(bus, nACK, nACK)) {
		ppb_1284_set_error(bus, PPB_TIMEOUT, 6);
		error = EBUSY;
		goto error;
	}

	/* Event 7 - quering result consider nACK not to misunderstand
	 * a remote computer terminate sequence */
	if (options & PPB_EXTENSIBILITY_LINK) {

		/* XXX not fully supported yet */
		ppb_1284_terminate(bus);
		return (0);

	}
	if (request_mode == NIBBLE_1284_NORMAL) {
		if (do_1284_wait(bus, nACK | SELECT, nACK)) {
			ppb_1284_set_error(bus, PPB_MODE_UNSUPPORTED, 7);
			error = ENODEV;
			goto error;
		}
	} else {
		if (do_1284_wait(bus, nACK | SELECT, SELECT | nACK)) {
			ppb_1284_set_error(bus, PPB_MODE_UNSUPPORTED, 7);
			error = ENODEV;
			goto error;
		}
	}

	switch (mode) {
	case PPB_NIBBLE:
	case PPB_PS2:
		/* enter reverse idle phase */
		ppb_1284_set_state(bus, PPB_REVERSE_IDLE);
		break;
	case PPB_ECP:
		/* negociation ok, now setup the communication */
		ppb_1284_set_state(bus, PPB_SETUP);
		ppb_wctr(bus, (nINIT | AUTOFEED) & ~(SELECTIN | STROBE));

#ifdef PERIPH_1284
		/* ignore PError line */
		if (do_1284_wait(bus, nACK | SELECT | nBUSY,
					nACK | SELECT | nBUSY)) {
			ppb_1284_set_error(bus, PPB_TIMEOUT, 30);
			error = ENODEV;
			goto error;
		}
#else
		if (do_1284_wait(bus, nACK | SELECT | PERROR | nBUSY,
					nACK | SELECT | PERROR | nBUSY)) {
			ppb_1284_set_error(bus, PPB_TIMEOUT, 30);
			error = ENODEV;
			goto error;
		}
#endif /* !PERIPH_1284 */

		/* ok, the host enters the ForwardIdle state */
		ppb_1284_set_state(bus, PPB_ECP_FORWARD_IDLE);
		break;
	case PPB_EPP:
		ppb_1284_set_state(bus, PPB_EPP_IDLE);
		break;

	default:
		panic("%s: unknown mode (%d)!", __func__, mode);
	}
	ppb_set_mode(bus, mode);

	return (0);

error:
	ppb_1284_terminate(bus);

	return (error);
}
示例#6
0
/*
 * ppb_peripheral_negociate()
 *
 * Negociate the peripheral side
 */
int
ppb_peripheral_negociate(device_t bus, int mode, int options)
{
	int spin, request_mode, error = 0;
	char r;

	ppb_set_mode(bus, PPB_COMPATIBLE);
	ppb_1284_set_state(bus, PPB_PERIPHERAL_NEGOCIATION);

	/* compute ext. value */
	request_mode = ppb_request_mode(mode, options);

	/* wait host */
	spin = 10;
	while (spin-- && (ppb_rstr(bus) & nBUSY))
		DELAY(1);

	/* check termination */
	if (!(ppb_rstr(bus) & SELECT) || !spin) {
		error = ENODEV;
		goto error;
	}

	/* Event 4 - read ext. value */
	r = ppb_rdtr(bus);

	/* nibble mode is not supported */
	if ((r == (char)request_mode) ||
			(r == NIBBLE_1284_NORMAL)) {

		/* Event 5 - restore direction bit, no data avail */
		ppb_wctr(bus, (STROBE | nINIT) & ~(SELECTIN));
		DELAY(1);

		/* Event 6 */
		ppb_wctr(bus, (nINIT) & ~(SELECTIN | STROBE));

		if (r == NIBBLE_1284_NORMAL) {
#ifdef DEBUG_1284
			printf("R");
#endif
			ppb_1284_set_error(bus, PPB_MODE_UNSUPPORTED, 4);
			error = EINVAL;
			goto error;
		} else {
			ppb_1284_set_state(bus, PPB_PERIPHERAL_IDLE);
			switch (r) {
			case BYTE_1284_NORMAL:
				ppb_set_mode(bus, PPB_BYTE);
				break;
			default:
				break;
			}
#ifdef DEBUG_1284
			printf("A");
#endif
			/* negociation succeeds */
		}
	} else {
		/* Event 5 - mode not supported */
		ppb_wctr(bus, SELECTIN);
		DELAY(1);

		/* Event 6 */
		ppb_wctr(bus, (SELECTIN) & ~(STROBE | nINIT));
		ppb_1284_set_error(bus, PPB_MODE_UNSUPPORTED, 4);

#ifdef DEBUG_1284
		printf("r");
#endif
		error = EINVAL;
		goto error;
	}

	return (0);

error:
	ppb_peripheral_terminate(bus, PPB_WAIT);
	return (error);
}