diff options
-rw-r--r-- | sys/amd64/amd64/io.c | 40 | ||||
-rw-r--r-- | sys/amd64/include/iodev.h | 21 | ||||
-rw-r--r-- | sys/dev/io/iodev.c | 146 | ||||
-rw-r--r-- | sys/dev/io/iodev.h | 44 | ||||
-rw-r--r-- | sys/i386/i386/io.c | 40 | ||||
-rw-r--r-- | sys/i386/include/iodev.h | 21 | ||||
-rw-r--r-- | sys/ia64/ia64/iodev_machdep.c | 104 | ||||
-rw-r--r-- | sys/ia64/include/iodev.h | 33 |
8 files changed, 251 insertions, 198 deletions
diff --git a/sys/amd64/amd64/io.c b/sys/amd64/amd64/io.c index 09d6e89..c2d0d51 100644 --- a/sys/amd64/amd64/io.c +++ b/sys/amd64/amd64/io.c @@ -28,60 +28,32 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> -#include <sys/conf.h> -#include <sys/fcntl.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/mutex.h> -#include <sys/priv.h> #include <sys/proc.h> -#include <sys/signalvar.h> -#include <sys/systm.h> -#include <machine/db_machdep.h> #include <machine/frame.h> -#include <machine/psl.h> -#include <machine/specialreg.h> - -#include <vm/vm.h> -#include <vm/pmap.h> - #include <machine/iodev.h> +#include <machine/psl.h> -/* ARGSUSED */ int -ioopen(struct cdev *dev __unused, int flags __unused, int fmt __unused, - struct thread *td) +iodev_open(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); td->td_frame->tf_rflags |= PSL_IOPL; - return (0); } -/* ARGSUSED */ int -ioclose(struct cdev *dev __unused, int flags __unused, int fmt __unused, - struct thread *td) +iodev_close(struct thread *td) { - td->td_frame->tf_rflags &= ~PSL_IOPL; + td->td_frame->tf_rflags &= ~PSL_IOPL; return (0); } /* ARGSUSED */ int -ioioctl(struct cdev *dev __unused, u_long cmd __unused, caddr_t data __unused, - int fflag __unused, struct thread *td __unused) +iodev_ioctl(u_long cmd __unused, caddr_t data __unused) { - return (ENXIO); + return (ENOIOCTL); } diff --git a/sys/amd64/include/iodev.h b/sys/amd64/include/iodev.h index 1a0a17a..9f53cac 100644 --- a/sys/amd64/include/iodev.h +++ b/sys/amd64/include/iodev.h @@ -25,7 +25,22 @@ * * $FreeBSD$ */ +#ifndef _MACHINE_IODEV_H_ +#define _MACHINE_IODEV_H_ -d_open_t ioopen; -d_close_t ioclose; -d_ioctl_t ioioctl; +#ifdef _KERNEL +#include <machine/cpufunc.h> + +#define iodev_read_1 inb +#define iodev_read_2 inw +#define iodev_read_4 inl +#define iodev_write_1 outb +#define iodev_write_2 outw +#define iodev_write_4 outl + +int iodev_open(struct thread *td); +int iodev_close(struct thread *td); +int iodev_ioctl(u_long cmd, caddr_t data); + +#endif /* _KERNEL */ +#endif /* _MACHINE_IODEV_H_ */ 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_ */ diff --git a/sys/i386/i386/io.c b/sys/i386/i386/io.c index c392af5..152f6b1 100644 --- a/sys/i386/i386/io.c +++ b/sys/i386/i386/io.c @@ -28,60 +28,32 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> -#include <sys/conf.h> -#include <sys/fcntl.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/mutex.h> -#include <sys/priv.h> #include <sys/proc.h> -#include <sys/signalvar.h> -#include <sys/systm.h> -#include <machine/db_machdep.h> #include <machine/frame.h> -#include <machine/psl.h> -#include <machine/specialreg.h> - -#include <vm/vm.h> -#include <vm/pmap.h> - #include <machine/iodev.h> +#include <machine/psl.h> -/* ARGSUSED */ int -ioopen(struct cdev *dev __unused, int flags __unused, int fmt __unused, - struct thread *td) +iodev_open(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); td->td_frame->tf_eflags |= PSL_IOPL; - return (0); } -/* ARGSUSED */ int -ioclose(struct cdev *dev __unused, int flags __unused, int fmt __unused, - struct thread *td) +iodev_close(struct thread *td) { - td->td_frame->tf_eflags &= ~PSL_IOPL; + td->td_frame->tf_eflags &= ~PSL_IOPL; return (0); } /* ARGSUSED */ int -ioioctl(struct cdev *dev __unused, u_long cmd __unused, caddr_t data __unused, - int fflag __unused, struct thread *td __unused) +iodev_ioctl(u_long cmd __unused, caddr_t data __unused) { - return (ENXIO); + return (ENOIOCTL); } diff --git a/sys/i386/include/iodev.h b/sys/i386/include/iodev.h index 1a0a17a..9f53cac 100644 --- a/sys/i386/include/iodev.h +++ b/sys/i386/include/iodev.h @@ -25,7 +25,22 @@ * * $FreeBSD$ */ +#ifndef _MACHINE_IODEV_H_ +#define _MACHINE_IODEV_H_ -d_open_t ioopen; -d_close_t ioclose; -d_ioctl_t ioioctl; +#ifdef _KERNEL +#include <machine/cpufunc.h> + +#define iodev_read_1 inb +#define iodev_read_2 inw +#define iodev_read_4 inl +#define iodev_write_1 outb +#define iodev_write_2 outw +#define iodev_write_4 outl + +int iodev_open(struct thread *td); +int iodev_close(struct thread *td); +int iodev_ioctl(u_long cmd, caddr_t data); + +#endif /* _KERNEL */ +#endif /* _MACHINE_IODEV_H_ */ diff --git a/sys/ia64/ia64/iodev_machdep.c b/sys/ia64/ia64/iodev_machdep.c index d255aae..9d9057d 100644 --- a/sys/ia64/ia64/iodev_machdep.c +++ b/sys/ia64/ia64/iodev_machdep.c @@ -40,61 +40,33 @@ __FBSDID("$FreeBSD$"); #include <machine/efi.h> #include <machine/iodev.h> -static int iodev_pio_read(struct iodev_pio_req *req); -static int iodev_pio_write(struct iodev_pio_req *req); - static int iodev_efivar_getvar(struct iodev_efivar_req *req); static int iodev_efivar_nextname(struct iodev_efivar_req *req); static int iodev_efivar_setvar(struct iodev_efivar_req *req); /* ARGSUSED */ int -ioopen(struct cdev *dev __unused, int flags __unused, int fmt __unused, - struct thread *td) +iodev_open(struct thread *td __unused) { - int error; - - error = priv_check(td, PRIV_IO); - if (error == 0) - error = securelevel_gt(td->td_ucred, 0); - return (error); + return (0); } /* ARGSUSED */ int -ioclose(struct cdev *dev __unused, int flags __unused, int fmt __unused, - struct thread *td __unused) +iodev_close(struct thread *td __unused) { return (0); } -/* ARGSUSED */ int -ioioctl(struct cdev *dev __unused, u_long cmd, caddr_t data, - int fflag __unused, struct thread *td __unused) +iodev_ioctl(u_long cmd, caddr_t data) { struct iodev_efivar_req *efivar_req; - struct iodev_pio_req *pio_req; int error; - error = ENOIOCTL; switch (cmd) { - case IODEV_PIO: - pio_req = (struct iodev_pio_req *)data; - switch (pio_req->access) { - case IODEV_PIO_READ: - error = iodev_pio_read(pio_req); - break; - case IODEV_PIO_WRITE: - error = iodev_pio_write(pio_req); - break; - default: - error = EINVAL; - break; - } - break; case IODEV_EFIVAR: efivar_req = (struct iodev_efivar_req *)data; efivar_req->result = 0; /* So it's well-defined */ @@ -113,75 +85,11 @@ ioioctl(struct cdev *dev __unused, u_long cmd, caddr_t data, break; } break; - } - - return (error); -} - -static int -iodev_pio_read(struct iodev_pio_req *req) -{ - - switch (req->width) { - case 1: - req->val = bus_space_read_io_1(req->port); - break; - case 2: - if (req->port & 1) { - req->val = bus_space_read_io_1(req->port); - req->val |= bus_space_read_io_1(req->port + 1) << 8; - } else - req->val = bus_space_read_io_2(req->port); - break; - case 4: - if (req->port & 1) { - req->val = bus_space_read_io_1(req->port); - req->val |= bus_space_read_io_2(req->port + 1) << 8; - req->val |= bus_space_read_io_1(req->port + 3) << 24; - } else if (req->port & 2) { - req->val = bus_space_read_io_2(req->port); - req->val |= bus_space_read_io_2(req->port + 2) << 16; - } else - req->val = bus_space_read_io_4(req->port); - break; - default: - return (EINVAL); - } - - return (0); -} - -static int -iodev_pio_write(struct iodev_pio_req *req) -{ - - switch (req->width) { - case 1: - bus_space_write_io_1(req->port, req->val); - break; - case 2: - if (req->port & 1) { - bus_space_write_io_1(req->port, req->val); - bus_space_write_io_1(req->port + 1, req->val >> 8); - } else - bus_space_write_io_2(req->port, req->val); - break; - case 4: - if (req->port & 1) { - bus_space_write_io_1(req->port, req->val); - bus_space_write_io_2(req->port + 1, req->val >> 8); - bus_space_write_io_1(req->port + 3, req->val >> 24); - } else if (req->port & 2) { - bus_space_write_io_2(req->port, req->val); - bus_space_write_io_2(req->port + 2, req->val >> 16); - } else - bus_space_write_io_4(req->port, req->val); - break; default: - return (EINVAL); + error = ENOIOCTL; } - return (0); + return (error); } static int diff --git a/sys/ia64/include/iodev.h b/sys/ia64/include/iodev.h index 6d2ae19..cf349d9 100644 --- a/sys/ia64/include/iodev.h +++ b/sys/ia64/include/iodev.h @@ -31,22 +31,16 @@ #include <sys/uuid.h> -struct iodev_pio_req { - u_int access; -#define IODEV_PIO_READ 0 -#define IODEV_PIO_WRITE 1 - u_int port; - u_int width; - u_int val; -}; - -#define IODEV_PIO _IOWR('I', 0, struct iodev_pio_req) +#ifdef _KERNEL +#include <machine/bus.h> +#endif -struct iodev_efivar_req { - u_int access; #define IODEV_EFIVAR_GETVAR 0 #define IODEV_EFIVAR_NEXTNAME 1 #define IODEV_EFIVAR_SETVAR 2 + +struct iodev_efivar_req { + u_int access; u_int result; /* errno value */ size_t namesize; u_short *name; /* UCS-2 */ @@ -59,11 +53,16 @@ struct iodev_efivar_req { #define IODEV_EFIVAR _IOWR('I', 1, struct iodev_efivar_req) #ifdef _KERNEL +#define iodev_read_1 bus_space_read_io_1 +#define iodev_read_2 bus_space_read_io_2 +#define iodev_read_4 bus_space_read_io_4 +#define iodev_write_1 bus_space_write_io_1 +#define iodev_write_2 bus_space_write_io_2 +#define iodev_write_4 bus_space_write_io_4 -d_open_t ioopen; -d_close_t ioclose; -d_ioctl_t ioioctl; - -#endif +int iodev_open(struct thread *td); +int iodev_close(struct thread *td); +int iodev_ioctl(u_long, caddr_t data); +#endif /* _KERNEL */ #endif /* _MACHINE_IODEV_H_ */ |