diff options
| author | Attilio Rao <attilio@FreeBSD.org> | 2010-04-28 15:38:01 +0000 |
|---|---|---|
| committer | Attilio Rao <attilio@FreeBSD.org> | 2010-04-28 15:38:01 +0000 |
| commit | d8b878873e7aa8df1972cc6a642804b17eb61087 (patch) | |
| tree | fa18924d920e93a232bbaba63497b39499a9b76b /sys/dev/io/iodev.c | |
| parent | ee6b5ace1f9b0df8fbf3ad4cd28c522032994834 (diff) | |
Notes
Diffstat (limited to 'sys/dev/io/iodev.c')
| -rw-r--r-- | sys/dev/io/iodev.c | 146 |
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) { |
