Writes out data to a character device.
#include <sys/device.h> #include <sys/types.h>
int ddwrite (devno, uiop, chan, ext) dev_t devno; struct uio *uiop; chan_t chan; int ext;
devno | Specifies the major and minor device numbers. |
uiop | Points to a uio structure describing the data area or areas from which to be written. |
chan | Specifies the channel number. |
ext | Specifies the extension parameter. |
When a program issues a write or writex subroutine call or when the fp_rwuio kernel service is used, the kernel calls the ddwrite entry point.
This entry point receives a pointer to a uio structure, which provides variables used to specify the data transfer operation.
Character device drivers can use the uwritec and uiomove kernel services to transfer data into and out of the user buffer area during a write subroutine call. These services are passed a pointer to the uio structure. They update the fields in the structure by the number of bytes transferred. The only fields in the uio structure that are not potentially modified by the data transfer are the uio_fmode and uio_segflg fields.
For most devices, the ddwrite routine queues the request to the device handler and then waits for it to finish. The waiting is typically accomplished by calling the e_sleep kernel service to wait for an event. The e_sleep kernel service suspends the driver and the process that called it and permits other processes to run.
When the I/O operation is completed, the device usually causes an interrupt, causing the device driver's interrupt handler to be called. The interrupt handler then calls the e_wakeup kernel service specifying the awaited event, thus allowing the ddwrite routine to resume.
The uio_resid field initially contains the total number of bytes to write to the device. If the device driver supports it, the uio_offset field indicates the byte offset on the device from where the write should start.
The uio_offset field is a 64 bit integer (offset_t) ; this allows the file system to send I/O requests to a device driver's read & write entry points which have logical offsets beyond 2 gigabytes. Device drivers must use care not to cause a loss of significance by assigning the offset to a 32 bit variable or using it in calculations that overflow a 32 bit variable.
If no error occurs, the uio_resid field should be 0 on return from the ddwrite routine to indicate that all requested bytes were written. If an error occurs, this field should contain the number of bytes remaining to be written when the error occurred.
If a write request starts at a valid device offset but extends past the end of the device's capabilities, no error should be returned. However, the uio_resid field should indicate the number of bytes not transferred. If the write starts at or past the end of the device's capabilities, no data should be transferred. An error code of ENXIO should be returned, and the uio_resid field should not be modified.
When the ddwrite entry point is provided for raw I/O to a block device, this routine usually uses the uphysio kernel service to translate requests into block I/O requests.
The ddwrite routine is executed only in the process environment. It should provide the required serialization of its data structures by using the locking kernel services in conjunction with a private lock word defined in the driver.
The ddwrite entry point can indicate an error condition to the caller by returning a nonzero return value. This causes the subroutine to return a value of -1. It also makes the return code available to the user-mode program in the errno global variable. The error code used should be one of the values defined in the /usr/include/sys/errno.h file.
When applicable, the return values defined in the POSIX 1003.1 standard for the write subroutine should be used.
The ddread device driver entry point.
The CIO_GET_FASTWRT ddioctl.
The e_sleep kernel service, e_wakeup kernel service, fp_rwuio kernel service, uiomove kernel service, uphysio kernel service, uwritec kernel service.
The uio structure.
The write and writex subroutines.
Device Driver Kernel Extension Overview, Understanding Device Driver Roles, Understanding Interrupts, Understanding Locking in AIX Kernel Extensions and Device Support Programming Concepts.