|
Kernel Functions for Drivers | ddi_copyout(9F) |
| ddi_copyout - copy data from a driver |
SYNOPSIS
|
#include <sys/types.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
int ddi_copyout(const void *driverbuf, void *buf, size_t cn, int flags); |
|
Solaris DDI specific (Solaris DDI).
|
|
-
driverbuf
- Source address in the driver from which the data is transferred.
-
buf
- Destination address to which the data is transferred.
-
cn
- Number of bytes to copy.
-
flags
- Set of flag bits that provide address space information about buf.
|
|
This routine is designed for use in driver ioctl(9E) routines for drivers that support layered ioctls. ddi_copyout() copies data from a
driver buffer to a destination address, buf.
The flags argument determines the address space information about buf. If the FKIOCTL flag is set, this indicates that buf is a kernel address, and ddi_copyout() behaves
like bcopy(9F). Otherwise, buf is interpreted as a user buffer address, and ddi_copyout() behaves like copyout(9F).
Addresses that are word-aligned are moved most efficiently. However, the driver developer is not obliged to ensure alignment. This function automatically finds the most efficient move algorithm according to address alignment.
|
|
Under normal conditions, 0 is returned to indicate a successful copy. Otherwise, -1 is returned if one of the following occurs:
- Paging fault; the driver tried to access a page of memory for which it did not have read or write access.
- Invalid user address, such as a user area or stack area.
- Invalid address that would have resulted in data being copied into the user block.
- Hardware fault; a hardware error prevented access to the specified user memory. For example, an uncorrectable parity or ECC error occurred.
If -1 is returned to the caller, driver entry point routines should return EFAULT.
|
|
ddi_copyout() can be called from user or kernel context only.
|
| Example 1. ddi_copyout example
|
A driver ioctl(9E) routine (line 12) can be used to get or set device attributes or registers. In the XX_GETREGS
condition (line 25), the driver copies the current device register values to another data area. If the specified argument contains an invalid address, an error code is returned.
|
1 struct device { /* layout of physical device registers */
2 int control; /* physical device control word */
3 int status; /* physical device status word */
4 short recv_char; /* receive character from device */
5 short xmit_char; /* transmit character to device */
6 };
7 struct device_state {
8 volatile struct device *regsp; /* pointer to device registers */
9 kmutex_t reg_mutex; /* protect device registers */
. . .
10 };
11 static void *statep; /* for soft state routines */
12 xxioctl(dev_t dev, int cmd, int arg, int mode,
13 cred_t *cred_p, int *rval_p)
14 {
15 struct device_state *sp;
16 volatile struct device *rp;
17 struct device reg_buf; /* temporary buffer for registers */
18 int instance;
19 instance = getminor(dev);
20 sp = ddi_get_soft_state(statep, instance);
21 if (sp == NULL)
22 return (ENXIO);
23 rp = sp->regsp;
. . .
24 switch (cmd) {
25 case XX_GETREGS: /* copy registers to arg */
26 mutex_enter(&sp->reg_mutex);
27 /*
28 * Copy data from device registers to
29 * temporary device register buffer
30 * e.g. reg_buf.control = rp->control;
31 */
32 mutex_exit(&sp->reg_mutex);
33 if (ddi_copyout(®_buf, arg,
34 sizeof (struct device), mode) != 0) {
35 return (EFAULT);
36 }
37 break;
38 }
39 }
|
|
|
|
The value of the flags argument to ddi_copyout() should be passed through directly from the mode argument of ioctl() untranslated.
Driver defined locks should not be held across calls to this function.
ddi_copyout() should not be used from a streams driver. See M_COPYIN and M_COPYOUT in STREAMS Programming Guide.
|
| |