Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/iicbus/iic.c
| Show All 25 Lines | |||||
| * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||
| * SUCH DAMAGE. | * SUCH DAMAGE. | ||||
| * | * | ||||
| */ | */ | ||||
| #include <sys/param.h> | #include <sys/param.h> | ||||
| #include <sys/abi_compat.h> | #include <sys/abi_compat.h> | ||||
| #include <sys/bus.h> | #include <sys/bus.h> | ||||
| #include <sys/conf.h> | #include <sys/conf.h> | ||||
| #include <sys/file.h> | |||||
| #include <sys/fcntl.h> | #include <sys/fcntl.h> | ||||
| #include <sys/lock.h> | #include <sys/lock.h> | ||||
| #include <sys/kernel.h> | #include <sys/kernel.h> | ||||
| #include <sys/malloc.h> | #include <sys/malloc.h> | ||||
| #include <sys/module.h> | #include <sys/module.h> | ||||
| #include <sys/proc.h> | |||||
| #include <sys/sx.h> | #include <sys/sx.h> | ||||
| #include <sys/systm.h> | #include <sys/systm.h> | ||||
| #include <sys/uio.h> | #include <sys/uio.h> | ||||
| #include <sys/errno.h> | #include <sys/errno.h> | ||||
| #include <dev/iicbus/iiconf.h> | #include <dev/iicbus/iiconf.h> | ||||
| #include <dev/iicbus/iicbus.h> | #include <dev/iicbus/iicbus.h> | ||||
| #include <dev/iicbus/iic.h> | #include <dev/iicbus/iic.h> | ||||
| ▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | |||||
| static int iic_probe(device_t); | static int iic_probe(device_t); | ||||
| static int iic_attach(device_t); | static int iic_attach(device_t); | ||||
| static int iic_detach(device_t); | static int iic_detach(device_t); | ||||
| static void iic_identify(driver_t *driver, device_t parent); | static void iic_identify(driver_t *driver, device_t parent); | ||||
| static void iicdtor(void *data); | static void iicdtor(void *data); | ||||
| static int iicuio_move(struct iic_cdevpriv *priv, struct uio *uio, int last); | static int iicuio_move(struct iic_cdevpriv *priv, struct uio *uio, int last); | ||||
| static int iicuio(struct cdev *dev, struct uio *uio, int ioflag); | static int iicuio(struct cdev *dev, struct uio *uio, int ioflag); | ||||
| static int iicrdwr(struct iic_cdevpriv *priv, struct iic_rdwr_data *d, int flags, bool compat32); | static int iicrdwr(struct iic_cdevpriv *priv, struct iic_rdwr_data *d, | ||||
| int flags, bool compat32, bool kernel_msgs); | |||||
| static int iic_linux_rdwr(struct file *fp, struct iic_rdwr_data *d, | |||||
| int flags, struct thread *td); | |||||
| static device_method_t iic_methods[] = { | static device_method_t iic_methods[] = { | ||||
| /* device interface */ | /* device interface */ | ||||
| DEVMETHOD(device_identify, iic_identify), | DEVMETHOD(device_identify, iic_identify), | ||||
| DEVMETHOD(device_probe, iic_probe), | DEVMETHOD(device_probe, iic_probe), | ||||
| DEVMETHOD(device_attach, iic_attach), | DEVMETHOD(device_attach, iic_attach), | ||||
| DEVMETHOD(device_detach, iic_detach), | DEVMETHOD(device_detach, iic_detach), | ||||
| ▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | iic_attach(device_t dev) | ||||
| sc->sc_devnode = make_dev(&iic_cdevsw, device_get_unit(dev), | sc->sc_devnode = make_dev(&iic_cdevsw, device_get_unit(dev), | ||||
| UID_ROOT, GID_WHEEL, | UID_ROOT, GID_WHEEL, | ||||
| 0600, "iic%d", device_get_unit(dev)); | 0600, "iic%d", device_get_unit(dev)); | ||||
| if (sc->sc_devnode == NULL) { | if (sc->sc_devnode == NULL) { | ||||
| device_printf(dev, "failed to create character device\n"); | device_printf(dev, "failed to create character device\n"); | ||||
| return (ENXIO); | return (ENXIO); | ||||
| } | } | ||||
| sc->sc_devnode->si_drv1 = sc; | sc->sc_devnode->si_drv1 = sc; | ||||
| sc->sc_devnode->si_drv2 = (void *)iic_linux_rdwr; | |||||
| return (0); | return (0); | ||||
| } | } | ||||
| static int | static int | ||||
| iic_detach(device_t dev) | iic_detach(device_t dev) | ||||
| { | { | ||||
| struct iic_softc *sc; | struct iic_softc *sc; | ||||
| ▲ Show 20 Lines • Show All 162 Lines • ▼ Show 20 Lines | for (i = 0; i < d->nmsgs; i++) { | ||||
| PTRIN_CP(msg32, buf[i], buf); | PTRIN_CP(msg32, buf[i], buf); | ||||
| } | } | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| #endif | #endif | ||||
| static int | static int | ||||
| iicrdwr(struct iic_cdevpriv *priv, struct iic_rdwr_data *d, int flags, | iicrdwr(struct iic_cdevpriv *priv, struct iic_rdwr_data *d, int flags, | ||||
| bool compat32 __unused) | bool compat32 __unused, bool kernel_msgs) | ||||
| { | { | ||||
| #ifdef COMPAT_FREEBSD32 | #ifdef COMPAT_FREEBSD32 | ||||
| struct iic_rdwr_data dswab; | struct iic_rdwr_data dswab; | ||||
| struct iic_rdwr_data32 *d32; | struct iic_rdwr_data32 *d32; | ||||
| #endif | #endif | ||||
| struct iic_msg *buf, *m; | struct iic_msg *buf, *m; | ||||
| void **usrbufs; | void **usrbufs; | ||||
| device_t iicdev, parent; | device_t iicdev, parent; | ||||
| Show All 17 Lines | #endif | ||||
| buf = malloc(sizeof(*d->msgs) * d->nmsgs, M_IIC, M_WAITOK); | buf = malloc(sizeof(*d->msgs) * d->nmsgs, M_IIC, M_WAITOK); | ||||
| #ifdef COMPAT_FREEBSD32 | #ifdef COMPAT_FREEBSD32 | ||||
| if (compat32) | if (compat32) | ||||
| error = iic_copyinmsgs32(d, buf); | error = iic_copyinmsgs32(d, buf); | ||||
| else | else | ||||
| #endif | #endif | ||||
| error = copyin(d->msgs, buf, sizeof(*d->msgs) * d->nmsgs); | if (kernel_msgs) | ||||
| memcpy(buf, d->msgs, sizeof(*d->msgs) * d->nmsgs); | |||||
| else | |||||
| error = copyin(d->msgs, buf, | |||||
| sizeof(*d->msgs) * d->nmsgs); | |||||
| if (error != 0) { | if (error != 0) { | ||||
| free(buf, M_IIC); | free(buf, M_IIC); | ||||
| return (error); | return (error); | ||||
| } | } | ||||
| /* Alloc kernel buffers for userland data, copyin write data */ | /* Alloc kernel buffers for userland data, copyin write data */ | ||||
| usrbufs = malloc(sizeof(void *) * d->nmsgs, M_IIC, M_WAITOK | M_ZERO); | usrbufs = malloc(sizeof(void *) * d->nmsgs, M_IIC, M_WAITOK | M_ZERO); | ||||
| Show All 33 Lines | #endif | ||||
| } | } | ||||
| free(usrbufs, M_IIC); | free(usrbufs, M_IIC); | ||||
| free(buf, M_IIC); | free(buf, M_IIC); | ||||
| return (error); | return (error); | ||||
| } | } | ||||
| static int | static int | ||||
| iic_linux_rdwr(struct file *fp, struct iic_rdwr_data *d, int flags, | |||||
| struct thread *td) | |||||
| { | |||||
| struct file *saved_fp; | |||||
| struct iic_cdevpriv *priv; | |||||
| int error; | |||||
| saved_fp = td->td_fpop; | |||||
| td->td_fpop = fp; | |||||
| error = devfs_get_cdevpriv((void **)&priv); | |||||
| td->td_fpop = saved_fp; | |||||
| if (error != 0) | |||||
| return (error); | |||||
| IIC_LOCK(priv); | |||||
| error = iicrdwr(priv, d, flags, false, true); | |||||
| IIC_UNLOCK(priv); | |||||
| return (error); | |||||
| } | |||||
| static int | |||||
| iicioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *td) | iicioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *td) | ||||
| { | { | ||||
| #ifdef COMPAT_FREEBSD32 | #ifdef COMPAT_FREEBSD32 | ||||
| struct iiccmd iicswab; | struct iiccmd iicswab; | ||||
| #endif | #endif | ||||
| device_t parent, iicdev; | device_t parent, iicdev; | ||||
| struct iiccmd *s; | struct iiccmd *s; | ||||
| #ifdef COMPAT_FREEBSD32 | #ifdef COMPAT_FREEBSD32 | ||||
| ▲ Show 20 Lines • Show All 141 Lines • ▼ Show 20 Lines | case I2CRDWR: | ||||
| } | } | ||||
| #ifdef COMPAT_FREEBSD32 | #ifdef COMPAT_FREEBSD32 | ||||
| compat32 = (cmd == I2CRDWR32); | compat32 = (cmd == I2CRDWR32); | ||||
| #else | #else | ||||
| compat32 = false; | compat32 = false; | ||||
| #endif | #endif | ||||
| error = iicrdwr(priv, (struct iic_rdwr_data *)data, flags, | error = iicrdwr(priv, (struct iic_rdwr_data *)data, flags, | ||||
| compat32); | compat32, false); | ||||
| break; | break; | ||||
| case I2CRPTSTART: | case I2CRPTSTART: | ||||
| if (!priv->started) { | if (!priv->started) { | ||||
| error = EINVAL; | error = EINVAL; | ||||
| break; | break; | ||||
| } | } | ||||
| Show All 18 Lines | |||||