The Solaris kernel runs in 64-bit mode on suitable hardware and supports both 32-bit and 64-bit applications. A 64-bit device driver is required to support I/O control commands from 32-bit and 64-bit user mode programs. The difference between a 32-bit program and a 64-bit program is its C language type model: a 32-bit program is ILP32 and a 64-bit program is LP64. See Appendix F, Making a Device Driver 64-Bit Ready , for information on C data type models.
Any data that flows between programs and the kernel and vice versa (for example using ddi_copyin(9F) or ddi_copyout(9F)) will either need to be identical in format regardless of the type model of the kernel and application, or the device driver should be able to handle a model mismatch between it and the application and adjust the data format accordingly.
To determine if there is a model mismatch, the ioctl(9E) mode parameter passes the data model bits to the driver. As Example 9-15 shows, the mode parameter is then passed to ddi_model_convert_from(9F) to determine if any model conversion is necessary.
In the following example, the driver copies a data structure which contains a user address. Because the data structure changes size from ILP32 to LP64, the 64-bit driver uses a 32-bit version of the structure when communicating with a 32-bit application.
struct args32 { uint32_t addr; /* 32-bit address in LP64 */ int len; } struct args { caddr_t addr; /* 64-bit address in LP64 */ int len; } static int xxioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) { struct xxstate *xsp; struct args a; xsp = ddi_get_soft_state(statep, getminor(dev)); if (xsp == NULL) { return (ENXIO); } switch (cmd) { case XX_COPYIN_DATA: switch(ddi_model_convert_from(mode & FMODELS)) { case DDI_MODEL_ILP32: { struct args32 a32; /* copy 32-bit args data shape */ if (ddi_copyin((void *)arg, &a32, sizeof (struct args32), mode) != 0) { return (EFAULT); } /* convert 32-bit to 64-bit args data shape */ a.addr = a32.addr; a.len = a32.len; break; } case DDI_MODEL_NONE: /* application and driver have same data model. */ if (ddi_copyin((void *)arg, &a, sizeof (struct args), mode) != 0) { return (EFAULT); } } /* continue using data shape in native driver data model. */ break; case XX_COPYOUT_DATA: /* copyout handling */ break; default: /* generic "ioctl unknown" error */ return (ENOTTY); } return (0); }