|
|
The following example is a listing of a kernel module that uses the EELS API. The module provides an ioctl interface so that messages can be sent directly from a test application to the kernel driver.
/*
* EELS test driver - provides an ioctl() interface to
* enable the user to connect and submit log messages
* as though originating from a normal kernel driver
*/
#ifdef _KERNEL_HEADERS
#include <util/types.h>
#include <svc/errno.h>
#include <io/conf.h>
#include <util/debug.h>
#include <io/eels/sys/eels_inf.h>
#include <io/eels/eels_test/eels_drvr/eels_edt.h>
#include <mem/kmem.h>
#include <util/ksynch.h>
#include <util/mod/moddefs.h>
#include <io/ddi.h>
#else
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/conf.h>
#include <sys/debug.h>
#include <sys/eels_inf.h>
#include <sys/eels_edt.h>
#include <sys/kmem.h>
#include <sys/ksynch.h>
#include <sys/moddefs.h>
#include <sys/ddi.h>
#endif
int edt_load(void);
int edt_unload(void);
int edtopen(dev_t *, int, int, cred_t *);
int edtclose(dev_t , int, int, cred_t *);
int edtioctl(dev_t , int, void *, int, cred_t *, int *);
int edtdevflag = D_MP;
MOD_DRV_WRAPPER(edt, edt_load, edt_unload, NULL, "eels test driver");
edt_load()
{
return 0;
}
edt_unload()
{
return 0;
}
/*
* Open the edt device.
*/
int
edtopen(dev_t *devp, int oflags, int otyp, cred_t *crp)
{
return 0;
}
/*
* Close the edt device.
*/
int
edtclose(dev_t dev, int oflags, int otyp, cred_t *crp)
{
return 0;
}
/*
* The main guts of the driver. Stage user supplied requests
* to the EELS driver and configure the stream as required.
*/
int
edtioctl(dev_t dev, int cmd, void *arg, int mode, cred_t *crp, int *rvalp)
{
eels_handle_t handle = 0;
edt_i_log_t log, *logp;
edt_i_connect_t con, *conp;
size_t size;
int retval;
switch(cmd) {
case I_EDT_LOG:
/* Issue an eels_log() call using supplied parameters */
if (copyin(arg, &log, sizeof(log))) {
return EFAULT;
}
if (log.strlen == 0) {
return EINVAL;
}
size = log.strlen + sizeof(log) - 1;
logp = kmem_zalloc(size, KM_NOSLEEP);
if (logp == NULL) {
return EFAULT;
}
if (copyin(arg, logp, size)) {
return EFAULT;
}
eels_log(logp->handle, logp->level, &logp->str);
kmem_free(logp, size);
break;
case I_EDT_CONNECT:
/* Issue an eels_initialise() call using supplied parameters */
if (copyin(arg, &con, sizeof(con))) {
return EFAULT;
}
if (con.desclen == 0) {
return EINVAL;
}
size = con.desclen + sizeof(con) - 1;
conp = kmem_zalloc(size, KM_NOSLEEP);
if (conp == NULL) {
return EFAULT;
}
if (copyin(arg, conp, size)) {
kmem_free(conp, size);
return EFAULT;
}
/* Now pass the description to the eels_initialise() call */
retval = eels_initialise(&handle, &conp->desc);
kmem_free(conp, size);
if (retval) {
return retval;
} else {
con.handle = handle;
if (copyout(&con, arg, sizeof(con))) {
return EFAULT;
}
}
break;
case I_EDT_TERMINATE:
/* Issue an eels_terminate() call using supplied parameters */
handle = (eels_handle_t )arg;
return eels_terminate( handle );
default:
return EINVAL;
}
return 0;
}