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.
This commit is contained in:
parent
bc8c6150b8
commit
5ac8fc29a5
@ -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);
|
||||
|
@ -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;
|
||||
struct file *fp;
|
||||
int error;
|
||||
|
||||
devclass = devclass_find("amr");
|
||||
if (devclass == NULL)
|
||||
return (ENOENT);
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user