コード例 #1
0
ファイル: iic.c プロジェクト: cyrilmagsuci/freebsd
static int
iicuio(struct cdev *dev, struct uio *uio, int ioflag)
{
	device_t parent;
	struct iic_cdevpriv *priv;
	int error;
	uint8_t addr;

	priv = NULL;
	error = devfs_get_cdevpriv((void**)&priv);

	if (error != 0)
		return (error);
	KASSERT(priv != NULL, ("iic cdevpriv should not be NULL!"));

	IIC_LOCK(priv);
	if (priv->started || (priv->addr == 0)) {
		IIC_UNLOCK(priv);
		return (ENXIO);
	}
	parent = device_get_parent(priv->sc->sc_dev);

	error = iicbus_request_bus(parent, priv->sc->sc_dev,
	    (ioflag & O_NONBLOCK) ? IIC_DONTWAIT : (IIC_WAIT | IIC_INTR));
	if (error != 0) {
		IIC_UNLOCK(priv);
		return (error);
	}

	if (uio->uio_rw == UIO_READ)
		addr = priv->addr | LSB;
	else
		addr = priv->addr & ~LSB;

	error = iicbus_start(parent, addr, 0);
	if (error != 0)
	{
		iicbus_release_bus(parent, priv->sc->sc_dev);
		IIC_UNLOCK(priv);
		return (error);
	}

	error = iicuio_move(priv, uio, IIC_LAST_READ);

	iicbus_stop(parent);
	iicbus_release_bus(parent, priv->sc->sc_dev);
	IIC_UNLOCK(priv);
	return (error);
}
コード例 #2
0
ファイル: iic.c プロジェクト: MarginC/kame
static int
iicread(dev_t dev, struct uio * uio, int ioflag)
{
    device_t iicdev = IIC_DEVICE(minor(dev));
    struct iic_softc *sc = IIC_SOFTC(minor(dev));
    int len, error = 0;
    int bufsize;

    if (!sc || !iicdev || !sc->sc_addr)
        return (EINVAL);

    if (sc->sc_count == 0)
        return (EINVAL);

    if ((error = iicbus_request_bus(device_get_parent(iicdev), iicdev, IIC_DONTWAIT)))
        return (error);

    /* max amount of data to read */
    len = min(uio->uio_resid, BUFSIZE);

    if ((error = iicbus_block_read(device_get_parent(iicdev), sc->sc_addr,
                                   sc->sc_inbuf, len, &bufsize)))
        return (error);

    if (bufsize > uio->uio_resid)
        panic("%s: too much data read!", __func__);

    iicbus_release_bus(device_get_parent(iicdev), iicdev);

    return (uiomove(sc->sc_inbuf, bufsize, uio));
}
コード例 #3
0
ファイル: iic.c プロジェクト: MarginC/kame
static int
iicwrite(dev_t dev, struct uio * uio, int ioflag)
{
    device_t iicdev = IIC_DEVICE(minor(dev));
    struct iic_softc *sc = IIC_SOFTC(minor(dev));
    int sent, error, count;

    if (!sc || !iicdev || !sc->sc_addr)
        return (EINVAL);

    if (sc->sc_count == 0)
        return (EINVAL);

    if ((error = iicbus_request_bus(device_get_parent(iicdev), iicdev, IIC_DONTWAIT)))
        return (error);

    count = min(uio->uio_resid, BUFSIZE);
    uiomove(sc->sc_buffer, count, uio);

    error = iicbus_block_write(device_get_parent(iicdev), sc->sc_addr,
                               sc->sc_buffer, count, &sent);

    iicbus_release_bus(device_get_parent(iicdev), iicdev);

    return(error);
}
コード例 #4
0
ファイル: iic.c プロジェクト: cyrilmagsuci/freebsd
static int
iicrdwr(struct iic_cdevpriv *priv, struct iic_rdwr_data *d, int flags)
{
	struct iic_msg *buf, *m;
	void **usrbufs;
	device_t iicdev, parent;
	int error, i;

	iicdev = priv->sc->sc_dev;
	parent = device_get_parent(iicdev);
	error = 0;

	buf = malloc(sizeof(*d->msgs) * d->nmsgs, M_IIC, M_WAITOK);

	error = copyin(d->msgs, buf, sizeof(*d->msgs) * d->nmsgs);

	/* Alloc kernel buffers for userland data, copyin write data */
	usrbufs = malloc(sizeof(void *) * d->nmsgs, M_IIC, M_WAITOK | M_ZERO);

	for (i = 0; i < d->nmsgs; i++) {
		m = &(buf[i]);
		usrbufs[i] = m->buf;

		/*
		 * At least init the buffer to NULL so we can safely free() it later.
		 * If the copyin() to buf failed, don't try to malloc bogus m->len.
		 */
		m->buf = NULL;
		if (error != 0)
			continue;
		m->buf = malloc(m->len, M_IIC, M_WAITOK);
		if (!(m->flags & IIC_M_RD))
			error = copyin(usrbufs[i], m->buf, m->len);
	}

	if (error == 0)
		error = iicbus_request_bus(parent, iicdev,
		    (flags & O_NONBLOCK) ? IIC_DONTWAIT : (IIC_WAIT | IIC_INTR));

	if (error == 0) {
		error = iicbus_transfer(iicdev, buf, d->nmsgs);
		iicbus_release_bus(parent, iicdev);
	}

	/* Copyout all read segments, free up kernel buffers */
	for (i = 0; i < d->nmsgs; i++) {
		m = &(buf[i]);
		if ((error == 0) && (m->flags & IIC_M_RD))
			error = copyout(m->buf, usrbufs[i], m->len);
		free(m->buf, M_IIC);
	}

	free(usrbufs, M_IIC);
	free(buf, M_IIC);
	return (error);
}
コード例 #5
0
ファイル: iic.c プロジェクト: MarginC/kame
static int
iicioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct thread *td)
{
    device_t iicdev = IIC_DEVICE(minor(dev));
    struct iic_softc *sc = IIC_SOFTC(minor(dev));
    device_t parent = device_get_parent(iicdev);
    struct iiccmd *s = (struct iiccmd *)data;
    int error, count;

    if (!sc)
        return (EINVAL);

    if ((error = iicbus_request_bus(device_get_parent(iicdev), iicdev,
                                    (flags & O_NONBLOCK) ? IIC_DONTWAIT :
                                    (IIC_WAIT | IIC_INTR))))
        return (error);

    switch (cmd) {
    case I2CSTART:
        error = iicbus_start(parent, s->slave, 0);

        /*
         * Implicitly set the chip addr to the slave addr passed as
         * parameter. Consequently, start/stop shall be called before
         * the read or the write of a block.
         */
        if (!error)
            sc->sc_addr = s->slave;

        break;

    case I2CSTOP:
        error = iicbus_stop(parent);
        break;

    case I2CRSTCARD:
        error = iicbus_reset(parent, 0, 0, NULL);
        break;

    case I2CWRITE:
        error = iicbus_write(parent, s->buf, s->count, &count, 10);
        break;

    case I2CREAD:
        error = iicbus_read(parent, s->buf, s->count, &count, s->last, 10);
        break;

    default:
        error = ENODEV;
    }

    iicbus_release_bus(device_get_parent(iicdev), iicdev);

    return (error);
}
コード例 #6
0
ファイル: iiconf.c プロジェクト: cyrilmagsuci/freebsd
int
iicbus_transfer_excl(device_t dev, struct iic_msg *msgs, uint32_t nmsgs,
                     int how)
{
    device_t bus;
    int error;

    bus = device_get_parent(dev);
    error = iicbus_request_bus(bus, dev, how);
    if (error == 0)
        error = IICBUS_TRANSFER(bus, msgs, nmsgs);
    iicbus_release_bus(bus, dev);
    return (error);
}
コード例 #7
0
ファイル: cambria_gpio.c プロジェクト: BillTheBest/libuinet
static int
cambria_gpio_write(struct cambria_gpio_softc *sc)
{
	device_t dev = sc->sc_dev;
	int error;

	error = iicbus_request_bus(device_get_parent(dev), dev,
	    IIC_DONTWAIT);
	if (error)
		return (error);

	i2c_sendstart(sc);
	i2c_sendbyte(sc, PLD_ADDR & ~LSB);
	i2c_sendbyte(sc, sc->sc_latch);
	i2c_sendstop(sc);

	iicbus_release_bus(device_get_parent(dev), dev);

	return (0);
}
コード例 #8
0
ファイル: cambria_gpio.c プロジェクト: BillTheBest/libuinet
static int
cambria_gpio_read(struct cambria_gpio_softc *sc, uint32_t pin, unsigned int *val)
{
	device_t dev = sc->sc_dev;
	int error;

	error = iicbus_request_bus(device_get_parent(dev), dev,
	    IIC_DONTWAIT);
	if (error)
		return (error);

	i2c_sendstart(sc);
	i2c_sendbyte(sc, PLD_ADDR | LSB);
	*val = (i2c_readbyte(sc) & (1 << pin)) != 0;
	i2c_sendstop(sc);

	iicbus_release_bus(device_get_parent(dev), dev);

	return (0);
}
コード例 #9
0
ファイル: iic.c プロジェクト: cyrilmagsuci/freebsd
static void
iicdtor(void *data)
{
	device_t iicdev, parent;
	struct iic_cdevpriv *priv;

	priv = data;
	KASSERT(priv != NULL, ("iic cdevpriv should not be NULL!"));

	iicdev = priv->sc->sc_dev;
	parent = device_get_parent(iicdev);

	if (priv->started) {
		iicbus_stop(parent);
		iicbus_reset(parent, IIC_UNKNOWN, 0, NULL);
		iicbus_release_bus(parent, iicdev);
	}

	sx_destroy(&priv->lock);
	free(priv, M_IIC);
}
コード例 #10
0
ファイル: if_ic.c プロジェクト: AhmadTux/DragonFlyBSD
/*
 * iciotcl()
 */
static int
icioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
{
    device_t icdev = devclass_get_device(ic_devclass, ifp->if_dunit);
    device_t parent = device_get_parent(icdev);
    struct ic_softc *sc = (struct ic_softc *)device_get_softc(icdev);

    struct ifaddr *ifa = (struct ifaddr *)data;
    struct ifreq *ifr = (struct ifreq *)data;

    u_char *iptr, *optr;
    int error;

    switch (cmd) {

    case SIOCSIFDSTADDR:
    case SIOCAIFADDR:
    case SIOCSIFADDR:
	if (ifa->ifa_addr->sa_family != AF_INET)
	    return EAFNOSUPPORT;
	ifp->if_flags |= IFF_UP;
	/* FALLTHROUGH */
    case SIOCSIFFLAGS:
	if ((!(ifp->if_flags & IFF_UP)) && (ifp->if_flags & IFF_RUNNING)) {

	    /* XXX disable PCF */
	    ifp->if_flags &= ~IFF_RUNNING;

	    /* IFF_UP is not set, try to release the bus anyway */
	    iicbus_release_bus(parent, icdev);
	    break;
	}
	if (((ifp->if_flags & IFF_UP)) && (!(ifp->if_flags & IFF_RUNNING))) {

	    if ((error = iicbus_request_bus(parent, icdev, IIC_WAIT|IIC_INTR)))
		return (error);

	    sc->ic_obuf = kmalloc(sc->ic_if.if_mtu + ICHDRLEN,
				  M_DEVBUF, M_WAITOK);

	    sc->ic_ifbuf = kmalloc(sc->ic_if.if_mtu + ICHDRLEN,
				  M_DEVBUF, M_WAITOK);

	    iicbus_reset(parent, IIC_FASTEST, 0, NULL);

	    ifp->if_flags |= IFF_RUNNING;
	}
	break;

    case SIOCSIFMTU:
	/* save previous buffers */
	iptr = sc->ic_ifbuf;
	optr = sc->ic_obuf;

	/* allocate input buffer */
	sc->ic_ifbuf = kmalloc(ifr->ifr_mtu+ICHDRLEN, M_DEVBUF, M_WAITOK);

	/* allocate output buffer */
	sc->ic_ifbuf = kmalloc(ifr->ifr_mtu+ICHDRLEN, M_DEVBUF, M_WAITOK);

	if (iptr)
	    kfree(iptr,M_DEVBUF);

	if (optr)
	    kfree(optr,M_DEVBUF);

	sc->ic_if.if_mtu = ifr->ifr_mtu;
	break;

    case SIOCGIFMTU:
	ifr->ifr_mtu = sc->ic_if.if_mtu;
	break;

    case SIOCADDMULTI:
    case SIOCDELMULTI:
	if (ifr == NULL) {
	    return EAFNOSUPPORT;		/* XXX */
	}
	switch (ifr->ifr_addr.sa_family) {

	case AF_INET:
	    break;

	default:
	    return EAFNOSUPPORT;
	}
	break;

    default:
	return EINVAL;
    }
    return 0;
}
コード例 #11
0
ファイル: iic.c プロジェクト: cyrilmagsuci/freebsd
static int
iicioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *td)
{
	device_t parent, iicdev;
	struct iiccmd *s;
	struct uio ubuf;
	struct iovec uvec;
	struct iic_cdevpriv *priv;
	int error;

	s = (struct iiccmd *)data;
	error = devfs_get_cdevpriv((void**)&priv);
	if (error != 0)
		return (error);

	KASSERT(priv != NULL, ("iic cdevpriv should not be NULL!"));

	iicdev = priv->sc->sc_dev;
	parent = device_get_parent(iicdev);
	IIC_LOCK(priv);


	switch (cmd) {
	case I2CSTART:
		if (priv->started) {
			error = EINVAL;
			break;
		}
		error = iicbus_request_bus(parent, iicdev,
		    (flags & O_NONBLOCK) ? IIC_DONTWAIT : (IIC_WAIT | IIC_INTR));

		if (error == 0)
			error = iicbus_start(parent, s->slave, 0);

		if (error == 0) {
			priv->addr = s->slave;
			priv->started = true;
		} else
			iicbus_release_bus(parent, iicdev);

		break;

	case I2CSTOP:
		if (priv->started) {
			error = iicbus_stop(parent);
			iicbus_release_bus(parent, iicdev);
			priv->started = false;
		}

		break;

	case I2CRSTCARD:
		/*
		 * Bus should be owned before we reset it.
		 * We allow the bus to be already owned as the result of an in-progress
		 * sequence; however, bus reset will always be followed by release
		 * (a new start is presumably needed for I/O anyway). */ 
		if (!priv->started)	
			error = iicbus_request_bus(parent, iicdev,
			    (flags & O_NONBLOCK) ? IIC_DONTWAIT : (IIC_WAIT | IIC_INTR));

		if (error == 0) {
			error = iicbus_reset(parent, IIC_UNKNOWN, 0, NULL);
			/*
			 * Ignore IIC_ENOADDR as it only means we have a master-only
			 * controller.
			 */
			if (error == IIC_ENOADDR)
				error = 0;

			iicbus_release_bus(parent, iicdev);
			priv->started = false;
		}
		break;

	case I2CWRITE:
		if (!priv->started) {
			error = EINVAL;
			break;
		}
		uvec.iov_base = s->buf;
		uvec.iov_len = s->count;
		ubuf.uio_iov = &uvec;
		ubuf.uio_iovcnt = 1;
		ubuf.uio_segflg = UIO_USERSPACE;
		ubuf.uio_td = td;
		ubuf.uio_resid = s->count;
		ubuf.uio_offset = 0;
		ubuf.uio_rw = UIO_WRITE;
		error = iicuio_move(priv, &ubuf, 0);
		break;

	case I2CREAD:
		if (!priv->started) {
			error = EINVAL;
			break;
		}
		uvec.iov_base = s->buf;
		uvec.iov_len = s->count;
		ubuf.uio_iov = &uvec;
		ubuf.uio_iovcnt = 1;
		ubuf.uio_segflg = UIO_USERSPACE;
		ubuf.uio_td = td;
		ubuf.uio_resid = s->count;
		ubuf.uio_offset = 0;
		ubuf.uio_rw = UIO_READ;
		error = iicuio_move(priv, &ubuf, s->last);
		break;

	case I2CRDWR:
		/*
		 * The rdwr list should be a self-contained set of
		 * transactions.  Fail if another transaction is in progress.
                 */
		if (priv->started) {
			error = EINVAL;
			break;
		}

		error = iicrdwr(priv, (struct iic_rdwr_data *)data, flags);

		break;

	case I2CRPTSTART:
		if (!priv->started) {
			error = EINVAL;
			break;
		}
		error = iicbus_repeated_start(parent, s->slave, 0);
		break;

	case I2CSADDR:
		priv->addr = *((uint8_t*)data);
		break;

	default:
		error = ENOTTY;
	}

	IIC_UNLOCK(priv);
	return (error);
}
コード例 #12
0
ファイル: if_ic.c プロジェクト: dcui/FreeBSD-9.3_kernel
/*
 * iciotcl()
 */
static int
icioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
	struct ic_softc *sc = ifp->if_softc;
	device_t icdev = sc->ic_dev;
	device_t parent = device_get_parent(icdev);
	struct ifaddr *ifa = (struct ifaddr *)data;
	struct ifreq *ifr = (struct ifreq *)data;
	int error;

	switch (cmd) {

	case SIOCSIFDSTADDR:
	case SIOCAIFADDR:
	case SIOCSIFADDR:
		if (ifa->ifa_addr->sa_family != AF_INET)
			return (EAFNOSUPPORT);
		mtx_lock(&sc->ic_lock);
		ifp->if_flags |= IFF_UP;
		goto locked;
	case SIOCSIFFLAGS:
		mtx_lock(&sc->ic_lock);
	locked:
		if ((!(ifp->if_flags & IFF_UP)) &&
		    (ifp->if_drv_flags & IFF_DRV_RUNNING)) {

			/* XXX disable PCF */
			ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
			mtx_unlock(&sc->ic_lock);

			/* IFF_UP is not set, try to release the bus anyway */
			iicbus_release_bus(parent, icdev);
			break;
		}
		if (((ifp->if_flags & IFF_UP)) &&
		    (!(ifp->if_drv_flags & IFF_DRV_RUNNING))) {
			mtx_unlock(&sc->ic_lock);
			if ((error = iicbus_request_bus(parent, icdev,
			    IIC_WAIT | IIC_INTR)))
				return (error);
			mtx_lock(&sc->ic_lock);
			iicbus_reset(parent, IIC_FASTEST, 0, NULL);
			ifp->if_drv_flags |= IFF_DRV_RUNNING;
		}
		mtx_unlock(&sc->ic_lock);
		break;

	case SIOCSIFMTU:
		ic_alloc_buffers(sc, ifr->ifr_mtu);
		break;

	case SIOCGIFMTU:
		mtx_lock(&sc->ic_lock);
		ifr->ifr_mtu = sc->ic_ifp->if_mtu;
		mtx_unlock(&sc->ic_lock);
		break;

	case SIOCADDMULTI:
	case SIOCDELMULTI:
		if (ifr == 0)
			return (EAFNOSUPPORT);		/* XXX */
		switch (ifr->ifr_addr.sa_family) {
		case AF_INET:
			break;
		default:
			return (EAFNOSUPPORT);
		}
		break;
	default:
		return (EINVAL);
	}
	return (0);
}