summaryrefslogtreecommitdiffstats
path: root/sys/dev/io
diff options
context:
space:
mode:
authorattilio <attilio@FreeBSD.org>2010-04-28 15:38:01 +0000
committerattilio <attilio@FreeBSD.org>2010-04-28 15:38:01 +0000
commit6dfd3f303086ff8e0db146c2e70c33de1a239696 (patch)
treefa18924d920e93a232bbaba63497b39499a9b76b /sys/dev/io
parent60e1354e61b43b340b1c25761d1b3d5fbc35b000 (diff)
downloadFreeBSD-src-6dfd3f303086ff8e0db146c2e70c33de1a239696.zip
FreeBSD-src-6dfd3f303086ff8e0db146c2e70c33de1a239696.tar.gz
- Extract the IODEV_PIO interface from ia64 and make it MI.
In the end, it does help fixing /dev/io usage from multithreaded processes. - On i386 and amd64 the old behaviour is kept but multithreaded processes must use the new interface in order to work well. - Support for the other architectures is greatly improved, where necessary, by the necessity to define very small things now. Manpage update will happen shortly. Sponsored by: Sandvine Incorporated PR: threads/116181 Reviewed by: emaste, marcel MFC after: 3 weeks
Diffstat (limited to 'sys/dev/io')
-rw-r--r--sys/dev/io/iodev.c146
-rw-r--r--sys/dev/io/iodev.h44
2 files changed, 181 insertions, 9 deletions
diff --git a/sys/dev/io/iodev.c b/sys/dev/io/iodev.c
index b142a39..eae69f4 100644
--- a/sys/dev/io/iodev.c
+++ b/sys/dev/io/iodev.c
@@ -30,22 +30,27 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/conf.h>
-#include <sys/fcntl.h>
#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
+#include <sys/ioccom.h>
#include <sys/module.h>
-#include <sys/mutex.h>
+#include <sys/priv.h>
#include <sys/proc.h>
-#include <sys/signalvar.h>
#include <sys/systm.h>
-#include <sys/uio.h>
-
-#include <vm/vm.h>
-#include <vm/pmap.h>
#include <machine/iodev.h>
+#include <dev/io/iodev.h>
+
+static int ioopen(struct cdev *dev, int flags, int fmt,
+ struct thread *td);
+static int ioclose(struct cdev *dev, int flags, int fmt,
+ struct thread *td);
+static int ioioctl(struct cdev *dev, u_long cmd, caddr_t data,
+ int fflag, struct thread *td);
+
+static int iopio_read(struct iodev_pio_req *req);
+static int iopio_write(struct iodev_pio_req *req);
+
static struct cdev *iodev;
static struct cdevsw io_cdevsw = {
@@ -58,6 +63,129 @@ static struct cdevsw io_cdevsw = {
/* ARGSUSED */
static int
+ioopen(struct cdev *dev __unused, int flags __unused, int fmt __unused,
+ struct thread *td)
+{
+ int error;
+
+ error = priv_check(td, PRIV_IO);
+ if (error != 0)
+ return (error);
+ error = securelevel_gt(td->td_ucred, 0);
+ if (error != 0)
+ return (error);
+ error = iodev_open(td);
+
+ return (error);
+}
+
+/* ARGSUSED */
+static int
+ioclose(struct cdev *dev __unused, int flags __unused, int fmt __unused,
+ struct thread *td)
+{
+
+ return (iodev_close(td));
+}
+
+/* ARGSUSED */
+static int
+ioioctl(struct cdev *dev __unused, u_long cmd, caddr_t data,
+ int fflag __unused, struct thread *td __unused)
+{
+ struct iodev_pio_req *pio_req;
+ int error;
+
+ switch (cmd) {
+ case IODEV_PIO:
+ pio_req = (struct iodev_pio_req *)data;
+ switch (pio_req->access) {
+ case IODEV_PIO_READ:
+ error = iopio_read(pio_req);
+ break;
+ case IODEV_PIO_WRITE:
+ error = iopio_write(pio_req);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ break;
+ default:
+ error = iodev_ioctl(cmd, data);
+ }
+
+ return (error);
+}
+
+static int
+iopio_read(struct iodev_pio_req *req)
+{
+
+ switch (req->width) {
+ case 1:
+ req->val = iodev_read_1(req->port);
+ break;
+ case 2:
+ if (req->port & 1) {
+ req->val = iodev_read_1(req->port);
+ req->val |= iodev_read_1(req->port + 1) << 8;
+ } else
+ req->val = iodev_read_2(req->port);
+ break;
+ case 4:
+ if (req->port & 1) {
+ req->val = iodev_read_1(req->port);
+ req->val |= iodev_read_2(req->port + 1) << 8;
+ req->val |= iodev_read_1(req->port + 3) << 24;
+ } else if (req->port & 2) {
+ req->val = iodev_read_2(req->port);
+ req->val |= iodev_read_2(req->port + 2) << 16;
+ } else
+ req->val = iodev_read_4(req->port);
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+static int
+iopio_write(struct iodev_pio_req *req)
+{
+
+ switch (req->width) {
+ case 1:
+ iodev_write_1(req->port, req->val);
+ break;
+ case 2:
+ if (req->port & 1) {
+ iodev_write_1(req->port, req->val);
+ iodev_write_1(req->port + 1, req->val >> 8);
+ } else
+ iodev_write_2(req->port, req->val);
+ break;
+ case 4:
+ if (req->port & 1) {
+ iodev_write_1(req->port, req->val);
+ iodev_write_2(req->port + 1, req->val >> 8);
+ iodev_write_1(req->port + 3, req->val >> 24);
+ } else if (req->port & 2) {
+ iodev_write_2(req->port, req->val);
+ iodev_write_2(req->port + 2, req->val >> 16);
+ } else
+ iodev_write_4(req->port, req->val);
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+/* ARGSUSED */
+static int
io_modevent(module_t mod __unused, int type, void *data __unused)
{
switch(type) {
diff --git a/sys/dev/io/iodev.h b/sys/dev/io/iodev.h
new file mode 100644
index 0000000..d040fccc
--- /dev/null
+++ b/sys/dev/io/iodev.h
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c) 2010 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _DEV_IODEV_H_
+#define _DEV_IODEV_H_
+
+#define IODEV_PIO_READ 0
+#define IODEV_PIO_WRITE 1
+
+struct iodev_pio_req {
+ u_int access;
+ u_int port;
+ u_int width;
+ u_int val;
+};
+
+#define IODEV_PIO _IOWR('I', 0, struct iodev_pio_req)
+
+#endif /* _DEV_IODEV_H_ */
OpenPOWER on IntegriCloud