/* ********************************************************** * Copyright 1998 - 2010 VMware, Inc. All rights reserved. * **********************************************************/ /* * @VMKAPIMOD_LICENSE@ */ /* *********************************************************************** * Character Devices */ /** * \defgroup CharDev Character Devices * * Interfaces that allow management of vmkernel's UNIX-like character * device nodes. * * @{ *********************************************************************** */ #ifndef _VMKAPI_CHAR_H_ #define _VMKAPI_CHAR_H_ /** \cond never */ #ifndef VMK_HEADER_INCLUDED_FROM_VMKAPI_H #error This vmkapi file should never be included directly but only via vmkapi.h #endif /** \endcond never */ /* * UNIX-style open flags supported for character devices */ /** \brief Read-only. */ #define VMK_CHARDEV_OFLAG_RDONLY 0x00000000 /** \brief Write-only. */ #define VMK_CHARDEV_OFLAG_WRONLY 0x00000001 /** \brief Read-write. */ #define VMK_CHARDEV_OFLAG_RDWR 0x00000002 /** \brief Mask for read/write flags. */ #define VMK_CHARDEV_OFLAG_RDWR_MASK 0x00000003 /** \brief Exclusive access. */ #define VMK_CHARDEV_OFLAG_EXCLUSIVE 0x00000080 /** \brief Append to end of file. Always set for writes */ #define VMK_CHARDEV_OFLAG_APPEND 0x00000400 /** \brief Don't block for file operations. */ #define VMK_CHARDEV_OFLAG_NONBLOCK 0x00000800 /** \brief Synchronous file operations. */ #define VMK_CHARDEV_OFLAG_SYNC 0x00001000 /** \brief Use direct I/O. */ #define VMK_CHARDEV_OFLAG_DIRECT 0x00004000 /** \brief Flags for poll entry point */ typedef enum vmk_PollEvent { /** \brief No events are available */ VMKAPI_POLL_NONE = 0x00, /** \brief The device is ready for reading */ VMKAPI_POLL_READ = 0x01, /** \brief The device is ready for writing */ VMKAPI_POLL_WRITE = 0x04, /** \brief The file was closed during polling for read status */ VMKAPI_POLL_RDHUP = 0x08, /** \brief The file was closed during polling for write status */ VMKAPI_POLL_WRHUP = 0x10, /** \brief The file is no longer valid */ VMKAPI_POLL_INVALID = 0x20, } vmk_PollEvent; /** * \brief Character device's file descriptor's attibutes. */ typedef struct vmk_CharDevFdAttr { /** * \brief UNIX-style file flags used when opening the device * from the host. */ vmk_uint32 openFlags; /** * \brief Client data associated with the device. * * This is device-specific data provided by the driver during * registration. */ vmk_AddrCookie clientDeviceData; /** * \brief Client data associated with the file descriptor. * * May be used by the character driver to store information * persistent across syscalls * * The field can be updated by the driver at any time during * a syscall. */ vmk_AddrCookie clientInstanceData; /* For use by the character device driver */ /* across open/ioctl/close calls */ } vmk_CharDevFdAttr; /** * \brief Opaque handle to a character device. */ typedef struct vmkCharDevInt* vmk_CharDev; /** * \brief A default initialization value for a vmk_CharDev. */ #define VMK_INVALID_CHARDEV (NULL) /** * \brief Opaque poll token handle. */ typedef void *vmk_PollToken; /** * \brief Opaque poll context handle. */ typedef void *vmk_PollContext; /** *********************************************************************** * vmk_CharDevOpenFn -- */ /** * * \brief A character device driver's open callback. * * If the open operation indicates success, the reference count for * the driver's module will be incremented, which will prevent the * module from being unloaded until the file is closed. It is * guaranteed that the driver's corresponding close callback will * be invoked for this attr object in the future if the open call * was successful (either when the user-space application closes the * file or when the application itself is closed). * If the open operation fails, no further operations for this attr * object will be issued. * * \note This callback is permitted to block. * * \param[in] attr File-descriptor attributes for this operation. * * \retval VMK_OK The open function completed successfully. * \retval Other The call failed and the error will be passed to * the user. * *********************************************************************** */ typedef VMK_ReturnStatus (*vmk_CharDevOpenFn)(vmk_CharDevFdAttr *attr); /** *********************************************************************** * vmk_CharDevCloseFn -- */ /** * * \brief A character device driver's close callback. * * If the driver's close operation fails, it will not be retried. After * executing the close callback, the driver module's reference count is * decremented, which may make the module eligible for unloading (if no * other outstanding references exist). * * \note This callback is permitted to block. * * \param[in] attr File-descriptor attributes for this operation. * * \retval VMK_OK The close function completed successfully. * \retval Other The call failed and the error will be passed to * the user. * *********************************************************************** */ typedef VMK_ReturnStatus (*vmk_CharDevCloseFn)(vmk_CharDevFdAttr *attr); /** *********************************************************************** * vmk_CharDevIoctlFn -- */ /** * * \brief A character device driver's ioctl callback. * * An ioctl callback may, depending on the convention of the ioctl * command, return two status codes. One is the return value of the * callback, and the other is returned via the result parameter. * For non-VMware (driver-specific) ioctl commands, the return * value only indicates whether or not the callback executed. In * this case, which is the usual case for third-party modules, the result * parameter's value indicates the integer status code that * should be passed back to the user process. * * Note that the userData may be a pointer from either a 32-bit or * a 64-bit process. The callerSize parameter instructs how the * ioctl callback should interpret the userData in the case it is a * pointer. * * \note This callback is permitted to block. * * \param[in] attr File-descriptor attributes for this operation. * \param[in] cmd Command code corresponding to the requested * operation. * \param[in,out] userData Opaque data passed by the user to the * ioctl command. May be a user-space pointer. * \param[in] callerSize The size (VMK_IOCTL_CALLER_32 or * VMK_IOCTL_CALLER_64) of the calling * process. * \param[out] result The result of the ioctl command, to be * passed to the user process. * * \retval VMK_OK The ioctl function completed successfully. * \retval Other The call failed and the error will be passed to * the user. * *********************************************************************** */ typedef VMK_ReturnStatus (*vmk_CharDevIoctlFn)(vmk_CharDevFdAttr *attr, unsigned int cmd, vmk_uintptr_t userData, vmk_IoctlCallerSize callerSize, vmk_int32 *result); /** *********************************************************************** * vmk_CharDevReadFn -- */ /** * * \brief A character device driver's read callback. * * The buffer for a read callback is a user-space buffer and therefore * must be written to indirectly using vmk_CopyToUser. * A read callback must always indicate how many bytes have been read, * even if an error was encountered during the read. The nature of the * error is then reflected in the return status. * * \note This callback is permitted to block. * * \param[in] attr File-descriptor attributes for this operation. * \param[out] buffer User buffer of bytes to write to. * \param[in] nbytes Number of bytes to read. * \param[in] ppos Offset associated with this read request. * \param[out] nread Number of bytes read. * * \retval VMK_OK The read function completed successfully. * \retval Other The call failed and the error will be passed to * the user. * *********************************************************************** */ typedef VMK_ReturnStatus (*vmk_CharDevReadFn)(vmk_CharDevFdAttr *attr, char *buffer, vmk_ByteCount nbytes, vmk_loff_t *ppos, vmk_ByteCountSigned *nread); /** *********************************************************************** * vmk_CharDevWriteFn -- */ /** * * \brief A character device driver's write callback. * * The buffer for a write callback is a user-space buffer and therefore * must be read from indirectly using vmk_CopyFromUser. * A write callback must always indicate how many bytes have been written, * even if an error was encountered during the write. The nature of the * error is then reflected in the return status. * * \note This callback is permitted to block. * * \param[in] attr File-descriptor attributes for this operation. * \param[in] buffer User buffer of bytes to read from. * \param[in] nbytes Number of bytes to write. * \param[in] ppos Offset associated with this write request. * \param[out] nwritten Number of bytes written. * * \retval VMK_OK The write function completed successfully. * \retval Other The call failed and the error will be passed to * the user. * *********************************************************************** */ typedef VMK_ReturnStatus (*vmk_CharDevWriteFn)(vmk_CharDevFdAttr *attr, char *buffer, vmk_ByteCount nbytes, vmk_loff_t *ppos, vmk_ByteCountSigned *nwritten); /** *********************************************************************** * vmk_CharDevPollFn -- */ /** * * \brief A character device driver's poll callback. * * \note This callback is permitted to block. * * \param[in] attr File-descriptor attributes for this operation. * \param[in] pollCtx Poll context of the calling thread. This * is an opaque handle supplied by the kernel. * The driver must associate a globally unique * token (such as a pointer) of its choosing * with this poll context using * vmk_CharDevSetPollContext. Poll wakeups * are thus performed, later, using * vmk_CharDevWakePollers by supplying that * driver-chosen token. * \param[out] pollMask Bitmask of vmk_PollEvent indicators * reflecting the current status of the * character device. * * \retval VMK_OK The poll function completed successfully. * \retval Other The call failed and the error will be passed to * the user. * *********************************************************************** */ typedef VMK_ReturnStatus (*vmk_CharDevPollFn)(vmk_CharDevFdAttr *attr, vmk_PollContext pollCtx, unsigned *pollMask); /** * \brief Character device driver's entry points */ typedef struct vmk_CharDevOps { vmk_CharDevOpenFn open; vmk_CharDevCloseFn close; vmk_CharDevIoctlFn ioctl; vmk_CharDevPollFn poll; vmk_CharDevReadFn read; vmk_CharDevWriteFn write; } vmk_CharDevOps; /** *********************************************************************** * vmk_CharDevCleanupFn -- */ /** * * \brief Prototype for a character device driver's cleanup callback. * * \param[in] private Optional private data to be used by the callback * * \retval VMK_OK The cleanup function executed correctly. * This is not an indicator of the success or failure of * the operations in the function, but merely that they * ran. Any other return value is not allowed. * *********************************************************************** */ typedef VMK_ReturnStatus (*vmk_CharDevCleanupFn)(vmk_AddrCookie private); /* *********************************************************************** * vmk_CharDevRegister -- */ /** * * \brief Register the specified character device, to be invoked from * user-space. * * \param[in] module Module that owns the character device. * \param[in] name The name of the device - this must be unique. * \param[in] fileOps Table of the driver file operations. * Neither open nor close can be supplied * without the other. * If read or write operations are supplied, * then open and close must also be supplied. * \param[in] cleanup Function automatically invoked to clean up * after all file ops have ceased and the * device has been unregistered. May be NULL. * \param[in] devicePrivate Data given to the driver for each file * op and cleaned up after unregistration. * \param[out] assignedHandle Handle to the registered character device. * * \retval VMK_EXISTS A device with that name is already registered * \retval VMK_FAILURE Unable to allocate internal slot for the device * \retval VMK_NO_MEMORY Unable to allocate memory for device metadata * \retval VMK_BAD_PARAM Module ID was invalid, name was invalid, * or one or more specified driver ops are NULL * *********************************************************************** */ VMK_ReturnStatus vmk_CharDevRegister( vmk_ModuleID module, const char *name, const vmk_CharDevOps *fileOps, vmk_CharDevCleanupFn cleanup, vmk_AddrCookie devicePrivate, vmk_CharDev *assignedHandle); /* *********************************************************************** * vmk_CharDevUnregister -- */ /** * * \brief Unregister a character device. * * The character device will be unregistered automatically by * the kernel only after all open files to the device have been * closed. If no files are open when vmk_CharDevUnregister is * called, the device may be unregistered immediately and have the * cleanup function registered with it invoked. If the device has * files open, vmk_CharDevUnregister internally defers the device for * later automatic removal and returns to the caller immediately. When * the last file is closed, the device will then be destroyed and the * cleanup function invoked. * * \note No new open files to the device can be created after calling * vmk_CharDevUnregister. * \note The vmkernel will prevent a module from being unloaded while * it has open files associated with a character device, even * if that device has been requested to be unregistered. * * \param[in] deviceHandle Handle of device assigned during registration. * * \retval VMK_NOT_FOUND The device does not exist. * \retval VMK_OK The device was either unregistered or internally * deferred for unregistration once all associated files * close. * *********************************************************************** */ VMK_ReturnStatus vmk_CharDevUnregister(vmk_CharDev deviceHandle); /* *********************************************************************** * vmk_CharDevWakePollers -- */ /** * * \brief Wake up all users waiting on a poll call with the specified * token. * * \param[in] token Context on which worlds are waiting. * *********************************************************************** */ void vmk_CharDevWakePollers(vmk_PollToken token); /* *********************************************************************** * vmk_CharDevSetPollContext -- */ /** * * \brief Set the poll context of the calling world to the specified * context. * * \param[in] pollCtx The poll context of the calling thread. * \param[out] token The token to set in the poll context. * *********************************************************************** */ void vmk_CharDevSetPollContext(vmk_PollContext pollCtx, vmk_PollToken *token); #endif /* _VMKAPI_CHAR_H_ */ /** @} */