Exemplo n.º 1
0
static int
xrpu_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *pr)
{
	struct softc *sc = dev->si_drv1;
	int i, error;

	if (sc->mode == TIMECOUNTER) {
		i = dev2pps(dev);
		if (i < 0 || i >= XRPU_MAX_PPS)
			return ENODEV;
		error =  pps_ioctl(cmd, arg, &sc->pps[i]);
		return (error);
	}
		
	if (cmd == XRPU_IOC_TIMECOUNTING) {
		struct xrpu_timecounting *xt = (struct xrpu_timecounting *)arg;

		/* Name SHALL be zero terminated */
		xt->xt_name[sizeof xt->xt_name - 1] = '\0';
		i = strlen(xt->xt_name);
		sc->tc.tc_name = (char *)malloc(i + 1, M_XRPU, M_WAITOK);
		strcpy(sc->tc.tc_name, xt->xt_name);
		sc->tc.tc_frequency = xt->xt_frequency;
		sc->tc.tc_get_timecount = xrpu_get_timecount;
		sc->tc.tc_poll_pps = xrpu_poll_pps;
		sc->tc.tc_priv = sc;
		sc->tc.tc_counter_mask = xt->xt_mask;
		sc->trigger = sc->virbase62 + xt->xt_addr_trigger;
		sc->latch = sc->virbase62 + xt->xt_addr_latch;

		for (i = 0; i < XRPU_MAX_PPS; i++) {
			if (xt->xt_pps[i].xt_addr_assert == 0
			    && xt->xt_pps[i].xt_addr_clear == 0)
				continue;
			make_dev(&xrpu_cdevsw, (i+1)<<16, 
			    UID_ROOT, GID_WHEEL, 0600, "xpps%d", i);
			sc->pps[i].ppscap = 0;
			if (xt->xt_pps[i].xt_addr_assert) {
				sc->assert[i] = sc->virbase62 + xt->xt_pps[i].xt_addr_assert;
				sc->pps[i].ppscap |= PPS_CAPTUREASSERT;
			}
			if (xt->xt_pps[i].xt_addr_clear) {
				sc->clear[i] = sc->virbase62 + xt->xt_pps[i].xt_addr_clear;
				sc->pps[i].ppscap |= PPS_CAPTURECLEAR;
			}
			pps_init(&sc->pps[i]);
		}
		sc->mode = TIMECOUNTER;
		init_timecounter(&sc->tc);
		return (0);
	}
	error = ENOTTY;
	return (error);
}
Exemplo n.º 2
0
/*
 * Set up the PPS cdev and the the kernel timepps stuff.
 *
 * Note that this routine cannot touch the hardware, because bus space resources
 * are not fully set up yet when this is called.
 */
static void
am335x_dmtimer_pps_init(device_t dev, struct am335x_dmtimer_softc *sc)
{
	int unit;

	if (am335x_dmtimer_pps_module == -1)
		am335x_dmtimer_pps_find();

	/* No PPS input */
	if (am335x_dmtimer_pps_module == 0)
		return;

	/* Not PPS-enabled input */
	if ((am335x_dmtimer_pps_module > 0) &&
	    (!ti_hwmods_contains(dev, am335x_dmtimer_pps_hwmod)))
	 	return;

	/*
	 * Indicate our capabilities (pretty much just capture of either edge).
	 * Have the kernel init its part of the pps_state struct and add its
	 * capabilities.
	 */
	sc->pps.ppscap = PPS_CAPTUREBOTH;
	pps_init(&sc->pps);

	/*
	 * Set up to capture the PPS via timecounter polling, and init the task
	 * that does deferred pps_event() processing after capture.
	 */
	sc->func.tc.tc_poll_pps = am335x_dmtimer_tc_poll_pps;
	TASK_INIT(&sc->pps_task, 0, am335x_dmtimer_process_pps_event, sc);

	/* Create the PPS cdev.  */
	unit = device_get_unit(dev);
	sc->pps_cdev = make_dev(&am335x_dmtimer_pps_cdevsw, unit, 
	    UID_ROOT, GID_WHEEL, 0600, PPS_CDEV_NAME);
	sc->pps_cdev->si_drv1 = sc;

	device_printf(dev, "Using DMTimer%d for PPS device /dev/%s%d\n", 
	    am335x_dmtimer_pps_module, PPS_CDEV_NAME, unit);
}
Exemplo n.º 3
0
/*
 * Set up the PPS cdev and the the kernel timepps stuff.
 *
 * Note that this routine cannot touch the hardware, because bus space resources
 * are not fully set up yet when this is called.
 */
static int
am335x_dmtimer_pps_init(device_t dev, struct am335x_dmtimer_softc *sc)
{
	int i, timer_num, unit;
	unsigned int padstate;
	const char * padmux;
	struct padinfo {
		char * ballname;
		char * muxname;
		int    timer_num;
	} padinfo[] = {
		{"GPMC_ADVn_ALE", "timer4", 4}, 
		{"GPMC_BEn0_CLE", "timer5", 5},
		{"GPMC_WEn",      "timer6", 6},
		{"GPMC_OEn_REn",  "timer7", 7},
	};

	/*
	 * Figure out which pin the user has set up for pps.  We'll use the
	 * first timer that has an external caputure pin configured as input.
	 *
	 * XXX The hieroglyphic "(padstate & (0x01 << 5)))" checks that the pin
	 * is configured for input.  The right symbolic values aren't exported
	 * yet from ti_scm.h.
	 */
	timer_num = 0;
	for (i = 0; i < nitems(padinfo) && timer_num == 0; ++i) {
		if (ti_scm_padconf_get(padinfo[i].ballname, &padmux, 
		    &padstate) == 0) {
			if (strcasecmp(padinfo[i].muxname, padmux) == 0 &&
			    (padstate & (0x01 << 5)))
				timer_num = padinfo[i].timer_num;
		}
	}

	if (timer_num == 0) {
		device_printf(dev, "No DMTimer found with capture pin "
		    "configured as input; PPS driver disabled.\n");
		return (DEFAULT_TC_TIMER);
	}

	/*
	 * Indicate our capabilities (pretty much just capture of either edge).
	 * Have the kernel init its part of the pps_state struct and add its
	 * capabilities.
	 */
	sc->pps.ppscap = PPS_CAPTUREBOTH;
	pps_init(&sc->pps);

	/*
	 * Set up to capture the PPS via timecounter polling, and init the task
	 * that does deferred pps_event() processing after capture.
	 */
	sc->tc.tc_poll_pps = am335x_dmtimer_tc_poll_pps;
	TASK_INIT(&sc->pps_task, 0, am335x_dmtimer_process_pps_event, sc);

	/* Create the PPS cdev.  */
	unit = device_get_unit(dev);
	sc->pps_cdev = make_dev(&am335x_dmtimer_pps_cdevsw, unit, 
	    UID_ROOT, GID_WHEEL, 0600, PPS_CDEV_NAME "%d", unit);
	sc->pps_cdev->si_drv1 = sc;

	device_printf(dev, "Using DMTimer%d for PPS device /dev/%s%d\n", 
	    timer_num, PPS_CDEV_NAME, unit);

	return (timer_num);
}
Exemplo n.º 4
0
int
ucomopen(dev_t dev, int flag, int mode, struct lwp *l)
{
	int unit = UCOMUNIT(dev);
	usbd_status err;
	struct ucom_softc *sc = device_lookup_private(&ucom_cd, unit);
	struct ucom_buffer *ub;
	struct tty *tp;
	int s, i;
	int error;

	if (sc == NULL)
		return (ENXIO);

	if (sc->sc_dying)
		return (EIO);

	if (!device_is_active(sc->sc_dev))
		return (ENXIO);

	tp = sc->sc_tty;

	DPRINTF(("ucomopen: unit=%d, tp=%p\n", unit, tp));

	if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
		return (EBUSY);

	s = spltty();

	/*
	 * Do the following iff this is a first open.
	 */
	while (sc->sc_opening)
		tsleep(&sc->sc_opening, PRIBIO, "ucomop", 0);

	if (sc->sc_dying) {
		splx(s);
		return (EIO);
	}
	sc->sc_opening = 1;

	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
		struct termios t;

		tp->t_dev = dev;

		if (sc->sc_methods->ucom_open != NULL) {
			error = sc->sc_methods->ucom_open(sc->sc_parent,
							  sc->sc_portno);
			if (error) {
				ucom_cleanup(sc);
				sc->sc_opening = 0;
				wakeup(&sc->sc_opening);
				splx(s);
				return (error);
			}
		}

		ucom_status_change(sc);

		/* Clear PPS capture state on first open. */
		mutex_spin_enter(&timecounter_lock);
		memset(&sc->sc_pps_state, 0, sizeof(sc->sc_pps_state));
		sc->sc_pps_state.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR;
		pps_init(&sc->sc_pps_state);
		mutex_spin_exit(&timecounter_lock);

		/*
		 * Initialize the termios status to the defaults.  Add in the
		 * sticky bits from TIOCSFLAGS.
		 */
		t.c_ispeed = 0;
		t.c_ospeed = TTYDEF_SPEED;
		t.c_cflag = TTYDEF_CFLAG;
		if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
			SET(t.c_cflag, CLOCAL);
		if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
			SET(t.c_cflag, CRTSCTS);
		if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
			SET(t.c_cflag, MDMBUF);
		/* Make sure ucomparam() will do something. */
		tp->t_ospeed = 0;
		(void) ucomparam(tp, &t);
		tp->t_iflag = TTYDEF_IFLAG;
		tp->t_oflag = TTYDEF_OFLAG;
		tp->t_lflag = TTYDEF_LFLAG;
		ttychars(tp);
		ttsetwater(tp);

		/*
		 * Turn on DTR.  We must always do this, even if carrier is not
		 * present, because otherwise we'd have to use TIOCSDTR
		 * immediately after setting CLOCAL, which applications do not
		 * expect.  We always assert DTR while the device is open
		 * unless explicitly requested to deassert it.  Ditto RTS.
		 */
		ucom_dtr(sc, 1);
		ucom_rts(sc, 1);

		DPRINTF(("ucomopen: open pipes in=%d out=%d\n",
			 sc->sc_bulkin_no, sc->sc_bulkout_no));

		/* Open the bulk pipes */
		err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no,
				     USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe);
		if (err) {
			DPRINTF(("%s: open bulk in error (addr %d), err=%s\n",
				 device_xname(sc->sc_dev), sc->sc_bulkin_no,
				 usbd_errstr(err)));
			error = EIO;
			goto fail_0;
		}
		err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no,
				     USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
		if (err) {
			DPRINTF(("%s: open bulk out error (addr %d), err=%s\n",
				 device_xname(sc->sc_dev), sc->sc_bulkout_no,
				 usbd_errstr(err)));
			error = EIO;
			goto fail_1;
		}

		sc->sc_rx_unblock = 0;
		sc->sc_rx_stopped = 0;
		sc->sc_tx_stopped = 0;

		memset(sc->sc_ibuff, 0, sizeof(sc->sc_ibuff));
		memset(sc->sc_obuff, 0, sizeof(sc->sc_obuff));

		SIMPLEQ_INIT(&sc->sc_ibuff_empty);
		SIMPLEQ_INIT(&sc->sc_ibuff_full);
		SIMPLEQ_INIT(&sc->sc_obuff_free);
		SIMPLEQ_INIT(&sc->sc_obuff_full);

		/* Allocate input buffers */
		for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS];
		    ub++) {
			ub->ub_xfer = usbd_alloc_xfer(sc->sc_udev);
			if (ub->ub_xfer == NULL) {
				error = ENOMEM;
				goto fail_2;
			}
			ub->ub_data = usbd_alloc_buffer(ub->ub_xfer,
			    sc->sc_ibufsizepad);
			if (ub->ub_data == NULL) {
				error = ENOMEM;
				goto fail_2;
			}

			if (ucomsubmitread(sc, ub) != USBD_NORMAL_COMPLETION) {
				error = EIO;
				goto fail_2;
			}
		}

		for (ub = &sc->sc_obuff[0]; ub != &sc->sc_obuff[UCOM_OUT_BUFFS];
		    ub++) {
			ub->ub_xfer = usbd_alloc_xfer(sc->sc_udev);
			if (ub->ub_xfer == NULL) {
				error = ENOMEM;
				goto fail_2;
			}
			ub->ub_data = usbd_alloc_buffer(ub->ub_xfer,
			    sc->sc_obufsize);
			if (ub->ub_data == NULL) {
				error = ENOMEM;
				goto fail_2;
			}

			SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_free, ub, ub_link);
		}

	}
	sc->sc_opening = 0;
	wakeup(&sc->sc_opening);
	splx(s);

	error = ttyopen(tp, UCOMDIALOUT(dev), ISSET(flag, O_NONBLOCK));
	if (error)
		goto bad;

	error = (*tp->t_linesw->l_open)(dev, tp);
	if (error)
		goto bad;

	return (0);

fail_2:
	usbd_abort_pipe(sc->sc_bulkin_pipe);
	for (i = 0; i < UCOM_IN_BUFFS; i++) {
		if (sc->sc_ibuff[i].ub_xfer != NULL) {
			usbd_free_xfer(sc->sc_ibuff[i].ub_xfer);
			sc->sc_ibuff[i].ub_xfer = NULL;
			sc->sc_ibuff[i].ub_data = NULL;
		}
	}
	usbd_abort_pipe(sc->sc_bulkout_pipe);
	for (i = 0; i < UCOM_OUT_BUFFS; i++) {
		if (sc->sc_obuff[i].ub_xfer != NULL) {
			usbd_free_xfer(sc->sc_obuff[i].ub_xfer);
			sc->sc_obuff[i].ub_xfer = NULL;
			sc->sc_obuff[i].ub_data = NULL;
		}
	}

	usbd_close_pipe(sc->sc_bulkout_pipe);
	sc->sc_bulkout_pipe = NULL;
fail_1:
	usbd_close_pipe(sc->sc_bulkin_pipe);
	sc->sc_bulkin_pipe = NULL;
fail_0:
	sc->sc_opening = 0;
	wakeup(&sc->sc_opening);
	splx(s);
	return (error);

bad:
	s = spltty();
	CLR(tp->t_state, TS_BUSY);
	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
		/*
		 * We failed to open the device, and nobody else had it opened.
		 * Clean up the state as appropriate.
		 */
		ucom_cleanup(sc);
	}
	splx(s);

	return (error);
}
Exemplo n.º 5
0
int
gtmpscopen(dev_t dev, int flag, int mode, struct lwp *l)
{
	struct gtmpsc_softc *sc;
	int unit = GTMPSCUNIT(dev);
	struct tty *tp;
	int s;
	int error;

	sc = device_lookup_private(&gtmpsc_cd, unit);
	if (!sc)
		return ENXIO;
#ifdef KGDB
	/*
	 * If this is the kgdb port, no other use is permitted.
	 */
	if (sc->sc_flags & GTMPSC_KGDB)
		return EBUSY;
#endif
	tp = sc->sc_tty;
	if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
		return EBUSY;

	s = spltty();

	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
		struct termios t;

		tp->t_dev = dev;

		mutex_spin_enter(&sc->sc_lock);

		/* Turn on interrupts. */
		sdma_imask |= SDMA_INTR_RXBUF(sc->sc_unit);
		gt_sdma_imask(device_parent(sc->sc_dev), sdma_imask);

		/* Clear PPS capture state on first open. */
		mutex_spin_enter(&timecounter_lock);
		memset(&sc->sc_pps_state, 0, sizeof(sc->sc_pps_state));
		sc->sc_pps_state.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR;
		pps_init(&sc->sc_pps_state);
		mutex_spin_exit(&timecounter_lock);

		mutex_spin_exit(&sc->sc_lock);

		if (sc->sc_flags & GTMPSC_CONSOLE) {
			t.c_ospeed = sc->sc_baudrate;
			t.c_cflag = sc->sc_cflag;
		} else {
			t.c_ospeed = TTYDEF_SPEED;
			t.c_cflag = TTYDEF_CFLAG;
		}
		t.c_ispeed = t.c_ospeed;

		/* Make sure gtmpscparam() will do something. */
		tp->t_ospeed = 0;
		(void) gtmpscparam(tp, &t);
		tp->t_iflag = TTYDEF_IFLAG;
		tp->t_oflag = TTYDEF_OFLAG;
		tp->t_lflag = TTYDEF_LFLAG;
		ttychars(tp);
		ttsetwater(tp);

		mutex_spin_enter(&sc->sc_lock);

		/* Clear the input/output ring */
		sc->sc_rcvcnt = 0;
		sc->sc_roffset = 0;
		sc->sc_rcvrx = 0;
		sc->sc_rcvdrx = 0;
		sc->sc_nexttx = 0;
		sc->sc_lasttx = 0;

		/*
		 * enable SDMA receive
		 */
		GT_SDMA_WRITE(sc, SDMA_SDCM, SDMA_SDCM_ERD);

		mutex_spin_exit(&sc->sc_lock);
	}
	splx(s);
	error = ttyopen(tp, GTMPSCDIALOUT(dev), ISSET(flag, O_NONBLOCK));
	if (error)
		goto bad;

	error = (*tp->t_linesw->l_open)(dev, tp);
	if (error)
		goto bad;

	return 0;

bad:
	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
		/*
		 * We failed to open the device, and nobody else had it opened.
		 * Clean up the state as appropriate.
		 */
		gtmpscshutdown(sc);
	}

	return error;
}