aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/io/iodev.c
diff options
context:
space:
mode:
authorAttilio Rao <attilio@FreeBSD.org>2010-04-28 15:38:01 +0000
committerAttilio Rao <attilio@FreeBSD.org>2010-04-28 15:38:01 +0000
commitd8b878873e7aa8df1972cc6a642804b17eb61087 (patch)
treefa18924d920e93a232bbaba63497b39499a9b76b /sys/dev/io/iodev.c
parentee6b5ace1f9b0df8fbf3ad4cd28c522032994834 (diff)
Notes
Diffstat (limited to 'sys/dev/io/iodev.c')
-rw-r--r--sys/dev/io/iodev.c146
1 files changed, 137 insertions, 9 deletions
diff --git a/sys/dev/io/iodev.c b/sys/dev/io/iodev.c
index b142a39c61070..eae69f484a4bd 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) {