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/amr/amr.c | |
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/amr/amr.c')
-rw-r--r-- | sys/dev/amr/amr.c | 37 |
1 files changed, 32 insertions, 5 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); |