STRUCT_DECL(9F) | Kernel Functions for Drivers | STRUCT_DECL(9F) |
STRUCT_DECL, SIZEOF_PTR, SIZEOF_STRUCT, STRUCT_BUF, STRUCT_FADDR, STRUCT_FGET, STRUCT_FGETP, STRUCT_FSET, STRUCT_FSETP, STRUCT_HANDLE, STRUCT_INIT, STRUCT_SIZE, STRUCT_SET_HANDLE - 32-bit application data access macros
#include <sys/ddi.h> #include <sys/sunddi.h> STRUCT_DECL(structname, handle);
STRUCT_HANDLE(structname, handle);
void STRUCT_INIT(handle, model_t umodel);
void STRUCT_SET_HANDLE(handle, model_t umodel, void *addr);
STRUCT_FGET(handle, field);
STRUCT_FGETP(handle, field);
STRUCT_FSET(handle, field, val);
STRUCT_FSETP(handle, field, val);
<typeof field> *STRUCT_FADDR(handle, field);
struct structname *STRUCT_BUF(handle);
size_t SIZEOF_STRUCT(structname, umodel);
size_t SIZEOF_PTR(umodel);
size_t STRUCT_SIZE(handle);
illumos DDI specific (illumos DDI).
The macros take the following parameters:
structname
umodel
handle
field
The above macros allow a device driver to access data consumed from a 32-bit application regardless whether the driver was compiled to the ILP32 or LP64 data model. These macros effectively hide the difference between the data model of the user application and the driver.
The macros can be broken up into two main categories described in the following sections.
The macros STRUCT_DECL() and STRUCT_HANDLE() declare structure handles on the stack, whereas the macros STRUCT_INIT() and STRUCT_SET_HANDLE() initialize the structure handles to point to an instance of the native form structure.
The macros STRUCT_HANDLE() and STRUCT_SET_HANDLE() are used to declare and initialize a structure handle to an existing data structure, for example, ioctls within a STREAMS module.
The macros STRUCT_DECL() and STRUCT_INIT(), on the other hand, are used in modules which declare and initialize a structure handle to a data structure allocated by STRUCT_DECL(), that is, any standard character or block device driver ioctl(9E) routine that needs to copy in data from a user-mode program.
STRUCT_DECL(structname, handle)
void STRUCT_INIT(handle, model_t umodel)
STRUCT_HANDLE(structname, handle)
void STRUCT_SET_HANDLE(handle, model_t umodel, void *addr)
size_t STRUCT_SIZE(handle)
STRUCT_FGET(handle, field)
STRUCT_FGETP(handle, field)
STRUCT_FSET(handle, field, val)
STRUCT_FSETP(handle, field, val)
struct structname *STRUCT_BUF(handle)
size_t SIZEOF_STRUCT(structname, umodel)
size_t SIZEOF_PTR(umodel)
Example 1 Copying a Structure
The following example uses an ioctl(9E) on a regular character device that copies a data structure that looks like this into the kernel:
struct opdata {
size_t size;
uint_t flag; };
Example 2 Defining a Structure
This data structure definition describes what the ioctl(9E) would look like in a 32-bit application using fixed width types.
#if defined(_MULTI_DATAMODEL) struct opdata32 {
size32_t size;
uint32_t flag; }; #endif
Example 3 Using STRUCT_DECL() and STRUCT_INIT()
Note: This example uses the STRUCT_DECL() and STRUCT_INIT() macros to declare and initialize the structure handle.
int xxioctl(dev_t dev, int cmd, intptr_t arg, int mode,
cred_t *cr, int *rval_p); {
STRUCT_DECL(opdata, op);
if (cmd != OPONE)
return (ENOTTY);
STRUCT_INIT(op, mode);
if (copyin((void *)data,
STRUCT_BUF(op), STRUCT_SIZE(op)))
return (EFAULT);
if (STRUCT_FGET(op, flag) != FACTIVE ||
STRUCT_FGET(op, size) > sizeof (device_state))
return (EINVAL);
xxdowork(device_state, STRUCT_FGET(op, size));
return (0); }
This piece of code is an excerpt from a STREAMS module that handles ioctl(9E) data (M_IOCDATA) messages and uses the data structure defined above. This code has been written to run in the ILP32 environment only.
Example 4 Using STRUCT_HANDLE() and STRUCT_SET_HANDLE()
The next example illustrates the use of the STRUCT_HANDLE() and STRUCT_SET_HANDLE() macros which declare and initialize the structure handle to point to an already existing instance of the structure.
The above code example can be converted to run in the LP64 environment using the STRUCT_HANDLE() and STRUCT_SET_HANDLE() as follows:
struct strbuf { int maxlen; /* no. of bytes in buffer */ int len; /* no. of bytes returned */ caddr_t buf; /* pointer to data */ };
static void wput_iocdata(queue_t *q, mblk_t *msgp) {
struct copyresp *cp = (struct copyresp *)msgp->b_rptr;
STRUCT_HANDLE(strbuf, sb);
if (msgp->b_cont->b_cont != NULL) {
msgp->b_cont = msgpullup(msgp->b_cont, -1);
if (msgp->b_cont == NULL) {
miocnak(q, msgp, 0, ENOSR);
return;
}
}
STRUCT_SET_HANDLE(sb, cp->cp_flag, (void *)msgp->b_cont->b_rptr);
if (STRUCT_FGET(sb, maxlen) < (int)sizeof (ipa_t)) {
miocnak(q, msgp, 0, ENOSR);
return;
}
...
miocack(q, msgp, 0, 0); }
See attributes(7) for descriptions of the following attributes:
ATTRIBUTE TYPE | ATTRIBUTE VALUE |
Interface Stability | Evolving |
devmap(9E), ioctl(9E), mmap(9E), ddi_mmap_get_model(9F)
Writing Device Drivers
STREAMS Programming Guide
May 20, 2006 | OmniOS |