diff options
author | ambrisko <ambrisko@FreeBSD.org> | 2006-05-03 16:45:15 +0000 |
---|---|---|
committer | ambrisko <ambrisko@FreeBSD.org> | 2006-05-03 16:45:15 +0000 |
commit | 5ac8fc29a50d17243ef3f7f055a226f1a2aba36f (patch) | |
tree | 0f74a33e8aae35668c42ade681ef8971900a6268 /sys/dev | |
parent | bc8c6150b8b8bcf7f4d87cd487737add8f446366 (diff) | |
download | FreeBSD-src-5ac8fc29a50d17243ef3f7f055a226f1a2aba36f.zip FreeBSD-src-5ac8fc29a50d17243ef3f7f055a226f1a2aba36f.tar.gz |
Make amr_linux work as a module by avoiding calling amr_linux_ioctl_int
from the amr_linux. This simplifies the amr_linux shim and puts the
smarts into amr.c.
I tested this with 2 amr controllers in one box. It seems to work
okay with them.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/amr/amr.c | 37 | ||||
-rw-r--r-- | sys/dev/amr/amr_linux.c | 129 | ||||
-rw-r--r-- | sys/dev/amr/amrvar.h | 2 |
3 files changed, 41 insertions, 127 deletions
diff --git a/sys/dev/amr/amr.c b/sys/dev/amr/amr.c index e3c0f28..561567d 100644 --- a/sys/dev/amr/amr.c +++ b/sys/dev/amr/amr.c @@ -110,6 +110,7 @@ static struct cdevsw amr_cdevsw = { .d_name = "amr", }; +int linux_no_adapter = 0; /* * Initialisation, bus interface. */ @@ -177,6 +178,8 @@ static void amr_printcommand(struct amr_command *ac); #endif static void amr_init_sysctl(struct amr_softc *sc); +static int amr_linux_ioctl_int(struct cdev *dev, u_long cmd, caddr_t addr, + int32_t flag, d_thread_t *td); /******************************************************************************** ******************************************************************************** @@ -258,6 +261,9 @@ amr_attach(struct amr_softc *sc) sc->amr_dev_t = make_dev(&amr_cdevsw, device_get_unit(sc->amr_dev), UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR, "amr%d", device_get_unit(sc->amr_dev)); sc->amr_dev_t->si_drv1 = sc; + linux_no_adapter++; + if (device_get_unit(sc->amr_dev) == 0) + make_dev_alias(sc->amr_dev_t, "megadev0"); /* * Schedule ourselves to bring the controller up once interrupts are @@ -542,9 +548,9 @@ amr_linux_ioctl_int(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, break; case 'm': - copyout(&sc->amr_linux_no_adapters, (void *)(uintptr_t)ali.data, - sizeof(sc->amr_linux_no_adapters)); - td->td_retval[0] = sc->amr_linux_no_adapters; + copyout(&linux_no_adapter, (void *)(uintptr_t)ali.data, + sizeof(linux_no_adapter)); + td->td_retval[0] = linux_no_adapter; error = 0; break; @@ -768,9 +774,30 @@ amr_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t * case 0xc0046d00: case 0xc06e6d00: /* Linux emulation */ - return amr_linux_ioctl_int(dev, cmd, addr, flag, td); - break; + { + devclass_t devclass; + struct amr_linux_ioctl ali; + int adapter, error; + + devclass = devclass_find("amr"); + if (devclass == NULL) + return (ENOENT); + error = copyin(addr, &ali, sizeof(ali)); + if (error) + return (error); + if (ali.ui.fcs.opcode == 0x82) + adapter = 0; + else + adapter = (ali.ui.fcs.adapno) ^ 'm' << 8; + + sc = devclass_get_softc(devclass, adapter); + if (sc == NULL) + return (ENOENT); + + return (amr_linux_ioctl_int(sc->amr_dev_t, cmd, + addr, 0, td)); + } default: debug(1, "unknown ioctl 0x%lx", cmd); return(ENOIOCTL); diff --git a/sys/dev/amr/amr_linux.c b/sys/dev/amr/amr_linux.c index 4a53424..0fe89d7 100644 --- a/sys/dev/amr/amr_linux.c +++ b/sys/dev/amr/amr_linux.c @@ -33,7 +33,8 @@ __FBSDID("$FreeBSD$"); #include <sys/conf.h> #include <sys/kernel.h> #include <sys/module.h> -#include <sys/bio.h> +#include <sys/file.h> +#include <sys/proc.h> #if defined(__amd64__) /* Assume amd64 wants 32 bit Linux */ #include <machine/../linux32/linux.h> @@ -44,14 +45,6 @@ __FBSDID("$FreeBSD$"); #endif #include <compat/linux/linux_ioctl.h> -#include <sys/bus.h> -#include <sys/stat.h> - -#include <machine/bus.h> - -#include <dev/amr/amrreg.h> -#include <dev/amr/amrvar.h> - /* There are multiple ioctl number ranges that need to be handled */ #define AMR_LINUX_IOCTL_MIN 0x6d00 #define AMR_LINUX_IOCTL_MAX 0x6d01 @@ -66,128 +59,24 @@ SYSINIT (amr_register, SI_SUB_KLD, SI_ORDER_MIDDLE, SYSUNINIT(amr_unregister, SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_unregister_handler, &amr_linux_handler); -static d_open_t amr_linux_open; -static d_close_t amr_linux_close; - -static int amr_linux_isopen; -static struct cdev * amr_linux_dev_t; - -static struct cdevsw megadev_cdevsw = { - .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, - .d_open = amr_linux_open, - .d_close = amr_linux_close, - .d_name = "megadev", -}; - - -static int -amr_linux_open(struct cdev * dev, int flags, int fmt, d_thread_t *td) -{ - - amr_linux_isopen++; - return (0); -}; - -static int -amr_linux_close(struct cdev * dev, int flags, int fmt, d_thread_t *td) -{ - - amr_linux_isopen--; - return (0); -}; - -static int -amr_linux_init(void) -{ - devclass_t devclass; - struct amr_softc *sc; - int i, linux_no_adapters, max_unit; - - devclass = devclass_find("amr"); - if (devclass == NULL) - return (0); - - max_unit = devclass_get_maxunit(devclass); - if (max_unit == 0) - return (0); - - for (i = 0; i < max_unit; i++) { - sc = devclass_get_softc(devclass, i); - if (sc == NULL) - break; - } - - linux_no_adapters = i; - for (i = 0; i < linux_no_adapters; i++) { - sc = devclass_get_softc(devclass, i); - if (sc == NULL) - break; - sc->amr_linux_no_adapters = linux_no_adapters; - } - - return (linux_no_adapters); -} - static int amr_linux_modevent(module_t mod, int cmd, void *data) { - - switch (cmd) { - case MOD_LOAD: - if (amr_linux_init() == 0) - return (ENXIO); - - if (amr_linux_dev_t) - return (EEXIST); - - amr_linux_dev_t = make_dev(&megadev_cdevsw, 0, UID_ROOT, - GID_OPERATOR, S_IRUSR | S_IWUSR, "megadev%d", 0); - if (amr_linux_dev_t == NULL) - return (ENXIO); - break; - - case MOD_UNLOAD: - if (amr_linux_isopen) - return (EBUSY); - if (amr_linux_dev_t) - destroy_dev(amr_linux_dev_t); - break; - - default: - return (EINVAL); - } return (0); } -static moduledata_t amr_linux_mod = {"amr_linux", amr_linux_modevent, NULL}; -DECLARE_MODULE(amr_linux, amr_linux_mod, SI_SUB_PSEUDO, SI_ORDER_MIDDLE); +DEV_MODULE(amr_linux, amr_linux_modevent, NULL); MODULE_DEPEND(amr, linux, 1, 1, 1); static int amr_linux_ioctl(d_thread_t *p, struct linux_ioctl_args *args) { - devclass_t devclass; - struct amr_softc *sc; - struct amr_linux_ioctl ali; - int adapter, error; - - devclass = devclass_find("amr"); - if (devclass == NULL) - return (ENOENT); + struct file *fp; + int error; - error = copyin((caddr_t)args->arg, &ali, sizeof(ali)); - if (error) + if ((error = fget(p, args->fd, &fp)) != 0) return (error); - if (ali.ui.fcs.opcode == 0x82) - adapter = 0; - else - adapter = (ali.ui.fcs.adapno) ^ 'm' << 8; - - sc = devclass_get_softc(devclass, adapter); - if (sc == NULL) - return (ENOENT); - - return (amr_linux_ioctl_int(sc->amr_dev_t, args->cmd, - (caddr_t)args->arg, 0, p)); + error = fo_ioctl(fp, args->cmd, (caddr_t)args->arg, p->td_ucred, p); + fdrop(fp, p); + return (error); } diff --git a/sys/dev/amr/amrvar.h b/sys/dev/amr/amrvar.h index 2f9a728..1fd78fd 100644 --- a/sys/dev/amr/amrvar.h +++ b/sys/dev/amr/amrvar.h @@ -254,8 +254,6 @@ extern void amr_free(struct amr_softc *sc); extern int amr_flush(struct amr_softc *sc); extern int amr_done(struct amr_softc *sc); extern void amr_startio(struct amr_softc *sc); -extern int amr_linux_ioctl_int(struct cdev *dev, u_long cmd, caddr_t addr, - int32_t flag, d_thread_t *td); /* * Command buffer allocation. |