/* * Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved. */ /* * The code contained herein is licensed under the GNU General Public * License. You may obtain a copy of the GNU General Public License * Version 2 or later at the following locations: * * http://www.opensource.org/licenses/gpl-license.html * http://www.gnu.org/copyleft/gpl.html */ #ifndef PORTABLE_OS_H #define PORTABLE_OS_H /***************************************************************************/ /* * Add support for your target OS by checking appropriate flags and then * including the appropriate file. Don't forget to document the conditions * in the later documentation section at the beginning of the * DOXYGEN_PORTABLE_OS_DOC. */ #if defined(LINUX_KERNEL) #include "linux_port.h" #elif defined(PORTABLE_OS) #include "check_portability.h" #else #error Target OS unsupported or unspecified #endif /***************************************************************************/ /*! * @file portable_os.h * * This file should be included by portable driver code in order to gain access * to the OS-specific header files. It is the only OS-related header file that * the writer of a portable driver should need. * * This file also contains the documentation for the common API. * * Begin reading the documentation for this file at the @ref index "main page". * */ /*! * @if USE_MAINPAGE * @mainpage Generic OS API for STC Drivers * @endif * * @section intro_sec Introduction * * This defines the API / kernel programming environment for portable drivers. * * This API is broken up into several functional areas. It greatly limits the * choices of a device-driver author, but at the same time should allow for * greater portability of the resulting code. * * Each kernel-to-driver function (initialization function, interrupt service * routine, etc.) has a 'portable signature' which must be used, and a specific * function which must be called to generate the return statement. There is * one exception, a background task or "bottom half" routine, which instead has * a specific structure which must be followed. These signatures and function * definitions are found in @ref drsigs. * * None of these kernel-to-driver functions seem to get any arguments passed to * them. Instead, there are @ref drsigargs which allow one of these functions * to get at fairly generic parts of its calling arguments, if there are any. * * Almost every driver will have some need to call the operating system * @ref dkops is the list of services which are available to the driver. * * * @subsection warn_sec Warning * * The specifics of the types, values of the various enumerations * (unless specifically stated, like = 0), etc., are only here for illustrative * purposes. No attempts should be made to make use of any specific knowledge * gleaned from this documentation. These types are only meant to be passed in * and out of the API, and their contents are to be handled only by the * provided OS-specific functions. * * Also, note that the function may be provided as macros in some * implementations, or vice versa. * * * @section dev_sec Writing a Portable Driver * * First off, writing a portable driver means calling no function in an OS * except what is available through this header file. * * Secondly, all OS-called functions in your driver must be invoked and * referenced through the signature routines. * * Thirdly, there might be some rules which you can get away with ignoring or * violating on one OS, yet will cause your code not to be portable to a * different OS. * * * @section limit_sec Limitations * * This API is not expected to handle every type of driver which may be found * in an operating system. For example, it will not be able to handle the * usual design for something like a UART driver, where there are multiple * logical devices to access, because the design usually calls for some sort of * indication to the #OS_DEV_TASK() function or OS_DEV_ISR() to indicate which * channel is to be serviced by that instance of the task/function. This sort * of argument is missing in this API for functions like os_dev_schedule_task() and * os_register_interrupt(). * * * @section port_guide Porting Guidelines * * This section is intended for a developer who needs to port the header file * to an operating system which is not yet supported. * * This interface allows for a lot of flexibility when it comes to porting to * an operating systems device driver interface. There are three main areas to * examine: The use of Driver Routine Signatures, the use of Driver Argument * Access functions, the Calls to Kernel Functions, and Data Types. * * * @subsection port_sig Porting Driver Routine Signatures * * The three macros for each function (e.g. #OS_DEV_INIT(), #OS_DEV_INIT_DCL(), * and #OS_DEV_INIT_REF()) allow the flexibility of having a 'wrapper' function * with the OS-required signature, which would then call the user's function * with some different signature. * * The first form would lay down the wrapper function, followed by the * signature for the user function. The second form would lay down just the * signatures for both functions, and the last function would reference the * wrapper function, since that is the interface function called by the OS. * * Note that the driver author has no visibility at all to the signature of the * routines. The author can access arguments only through a limited set of * functions, and must return via another function. * * The Return Functions allow a lot of flexibility in converting the return * value, or not returning a value at all. These will likely be implemented as * macros. * * * @subsection port_arg Porting Driver Argument Access Functions * * The signatures defined by the guide will usually be replaced with macro * definitions. * * * @subsection port_dki Porting Calls to Kernel Functions * * The signatures defined by the guide may be replaced with macro definitions, * if that makes more sense. * * Implementors are free to ignore arguments which are not applicable to their * OS. * * @subsection port_datatypes Porting Data Types * * */ /*************************************************************************** * Compile flags **************************************************************************/ /* * This compile flag should only be turned on when running doxygen to generate * the API documentation. */ #ifdef DOXYGEN_PORTABLE_OS_DOC /*! * @todo module_init()/module_cleanup() for Linux need to be added to OS * abstractions. Also need EXPORT_SYMBOL() equivalent?? * */ /* Drop OS differentation documentation here */ /*! * \#define this flag to build your driver as a Linux driver */ #define LINUX /* end OS differentation documentation */ /*! * Symbol to give version number of the implementation file. Earliest * definition is in version 1.1, with value 101 (to mean version 1.1) */ #define PORTABLE_OS_VERSION 101 /* * NOTICE: The following definitions (the rest of the file) are not meant ever * to be compiled. Instead, they are the documentation for the portable OS * API, to be used by driver writers. * * Each individual OS port will define each of these types, functions, or * macros as appropriate to the target OS. This is why they are under the * DOXYGEN_PORTABLE_OS_DOC flag. */ /*************************************************************************** * Type definitions **************************************************************************/ /*! * Type used for registering and deregistering interrupts. * * This is typically an interrupt channel number. */ typedef int os_interrupt_id_t; /*! * Type used as handle for a process * * See #os_get_process_handle() and #os_send_signal(). */ typedef int os_process_handle_t; /*! * Generic return code for functions which need such a thing. * * No knowledge should be assumed of the value of any of these symbols except * that @c OS_ERROR_OK_S is guaranteed to be zero. * * @todo Any other named values? What about (-EAGAIN? -ERESTARTSYS? Are they * too Linux/Unix-specific read()/write() return values) ? */ typedef enum { OS_ERROR_OK_S = 0, /*!< Success */ OS_ERROR_FAIL_S, /*!< Generic driver failure */ OS_ERROR_NO_MEMORY_S, /*!< Failure to acquire/use memory */ OS_ERROR_BAD_ADDRESS_S, /*!< Bad address */ OS_ERROR_BAD_ARG_S /*!< Bad input argument */ } os_error_code; /*! * Handle to a lock. */ typedef int *os_lock_t; /*! * Context while locking. */ typedef int os_lock_context_t; /*! * An object which can be slept on and later used to wake any/all sleepers. */ typedef int os_sleep_object_t; /*! * Driver registration handle */ typedef void *os_driver_reg_t; /*! * Function signature for an #OS_DEV_INIT() function. * * @return A call to os_dev_init_return() function. */ typedef void (*os_init_function_t) (void); /*! * Function signature for an #OS_DEV_SHUTDOWN() function. * * @return A call to os_dev_shutdown_return() function. */ typedef void (*os_shutdown_function_t) (void); /*! * Function signature for a user-driver function. * * @return A call to the appropriate os_dev_xxx_return() function. */ typedef void (*os_user_function_t) (void); /*! * Function signature for the portable interrupt handler * * While it would be nice to know which interrupt is being serviced, the * Least Common Denominator rule says that no arguments get passed in. * * @return A call to #os_dev_isr_return() */ typedef void (*os_interrupt_handler_t) (void); /*! * Function signature for a task function * * Many task function definitions get some sort of generic argument so that the * same function can run across many (queues, channels, ...) as separate task * instances. This has been left out of this API. * * This function must be structured as documented by #OS_DEV_TASK(). * */ typedef void (*os_task_fn_t) (void); /*! * Function types which can be associated with driver entry points. These are * used in os_driver_add_registration(). * * Note that init and shutdown are absent. */ typedef enum { OS_FN_OPEN, /*!< open() operation handler. */ OS_FN_CLOSE, /*!< close() operation handler. */ OS_FN_READ, /*!< read() operation handler. */ OS_FN_WRITE, /*!< write() operation handler. */ OS_FN_IOCTL, /*!< ioctl() operation handler. */ OS_FN_MMAP /*!< mmap() operation handler. */ } os_driver_fn_t; /*************************************************************************** * Driver-to-Kernel Operations **************************************************************************/ /*! * @defgroup dkops Driver-to-Kernel Operations * * These are the operations which drivers should call to get the OS to perform * services. */ /*! @addtogroup dkops */ /*! @{ */ /*! * Register an interrupt handler. * * @param driver_name The name of the driver * @param interrupt_id The interrupt line to monitor (type * #os_interrupt_id_t) * @param function The function to be called to handle an interrupt * * @return #os_error_code */ os_error_code os_register_interrupt(char *driver_name, os_interrupt_id_t interrupt_id, os_interrupt_handler_t function); /*! * Deregister an interrupt handler. * * @param interrupt_id The interrupt line to stop monitoring * * @return #os_error_code */ os_error_code os_deregister_interrupt(os_interrupt_id_t interrupt_id); /*! * Initialize driver registration. * * If the driver handles open(), close(), ioctl(), read(), write(), or mmap() * calls, then it needs to register their location with the kernel so that they * get associated with the device. * * @param handle The handle object to be used with this registration. The * object must live (be in memory somewhere) at least until * os_driver_remove_registration() is called. * * @return An os error code. */ os_error_code os_driver_init_registration(os_driver_reg_t handle); /*! * Add a function registration to driver registration. * * @param handle The handle used with #os_driver_init_registration(). * @param name Which function is being supported. * @param function The result of a call to a @c _REF version of one of the * driver function signature macros * driver function signature macros * @return void */ void os_driver_add_registration(os_driver_reg_t handle, os_driver_fn_t name, void *function); /*! * Finalize the driver registration with the kernel. * * Upon return from this call, the driver may begin receiving calls at the * defined entry points. * * @param handle The handle used with #os_driver_init_registration(). * @param major The major device number to be associated with the driver. * If this value is zero, a major number may be assigned. * See #os_driver_get_major() to determine final value. * #os_driver_remove_registration(). * @param driver_name The driver name. Can be used as part of 'device node' * name on platforms which support such a feature. * * @return An error code */ os_error_code os_driver_complete_registration(os_driver_reg_t handle, int major, char *driver_name); /*! * Get driver Major Number from handle after a successful registration. * * @param handle A handle which has completed registration. * * @return The major number (if any) associated with the handle. */ uint32_t os_driver_get_major(os_driver_reg_t handle); /*! * Remove the driver's registration with the kernel. * * Upon return from this call, the driver not receive any more calls at the * defined entry points (other than ISR and shutdown). * * @param major The major device number to be associated with the driver. * @param driver_name The driver name * * @return An error code. */ os_error_code os_driver_remove_registration(int major, char *driver_name); /*! * Print a message to console / into log file. After the @c msg argument a * number of printf-style arguments may be added. Types should be limited to * printf string, char, octal, decimal, and hexadecimal types. (This excludes * pointers, and floating point). * * @param msg The message to print to console / system log * * @return (void) */ void os_printk(char *msg, ...); /*! * Allocate some kernel memory * * @param amount Number of 8-bit bytes to allocate * @param flags Some indication of purpose of memory (needs definition) * * @return Pointer to allocated memory, or NULL if failed. */ void *os_alloc_memory(unsigned amount, int flags); /*! * Free some kernel memory * * @param location The beginning of the region to be freed. * * Do some OSes have separate free() functions which should be * distinguished by passing in @c flags here, too? Don't some also require the * size of the buffer being freed? Perhaps separate routines for each * alloc/free pair (DMAable, etc.)? */ void os_free_memory(void *location); /*! * Allocate cache-coherent memory * * @param amount Number of bytes to allocate * @param[out] dma_addrp Location to store physical address of allocated * memory. * @param flags Some indication of purpose of memory (needs * definition). * * @return (virtual space) pointer to allocated memory, or NULL if failed. * */ void *os_alloc_coherent(unsigned amount, uint32_t * dma_addrp, int flags); /*! * Free cache-coherent memory * * @param size Number of bytes which were allocated. * @param[out] virt_addr Virtual(kernel) address of memory.to be freed, as * returned by #os_alloc_coherent(). * @param[out] dma_addr Physical address of memory.to be freed, as returned * by #os_alloc_coherent(). * * @return void * */ void os_free_coherent(unsigned size, void *virt_addr, uint32_t dma_addr); /*! * Map an I/O space into kernel memory space * * @param start The starting address of the (physical / io space) region * @param range_bytes The number of bytes to map * * @return A pointer to the mapped area, or NULL on failure */ void *os_map_device(uint32_t start, unsigned range_bytes); /*! * Unmap an I/O space from kernel memory space * * @param start The starting address of the (virtual) region * @param range_bytes The number of bytes to unmap * * @return None */ void os_unmap_device(void *start, unsigned range_bytes); /*! * Copy data from Kernel space to User space * * @param to The target location in user memory * @param from The source location in kernel memory * @param size The number of bytes to be copied * * @return #os_error_code */ os_error_code os_copy_to_user(void *to, void *from, unsigned size); /*! * Copy data from User space to Kernel space * * @param to The target location in kernel memory * @param from The source location in user memory * @param size The number of bytes to be copied * * @return #os_error_code */ os_error_code os_copy_from_user(void *to, void *from, unsigned size); /*! * Read an 8-bit device register * * @param register_address The (bus) address of the register to write to * @return The value in the register */ uint8_t os_read8(uint8_t * register_address); /*! * Write an 8-bit device register * * @param register_address The (bus) address of the register to write to * @param value The value to write into the register */ void os_write8(uint8_t * register_address, uint8_t value); /*! * Read a 16-bit device register * * @param register_address The (bus) address of the register to write to * @return The value in the register */ uint16_t os_read16(uint16_t * register_address); /*! * Write a 16-bit device register * * @param register_address The (bus) address of the register to write to * @param value The value to write into the register */ void os_write16(uint16_t * register_address, uint16_t value); /*! * Read a 32-bit device register * * @param register_address The (bus) address of the register to write to * @return The value in the register */ uint32_t os_read32(uint32_t * register_address); /*! * Write a 32-bit device register * * @param register_address The (bus) address of the register to write to * @param value The value to write into the register */ void os_write32(uint32_t * register_address, uint32_t value); /*! * Read a 64-bit device register * * @param register_address The (bus) address of the register to write to * @return The value in the register */ uint64_t os_read64(uint64_t * register_address); /*! * Write a 64-bit device register * * @param register_address The (bus) address of the register to write to * @param value The value to write into the register */ void os_write64(uint64_t * register_address, uint64_t value); /*! * Prepare a task to execute the given function. This should only be done once * per task, during the driver's initialization routine. * * @param task_fn Name of the OS_DEV_TASK() function to be created. * * @return an OS ERROR code. */ os_error os_create_task(os_task_fn_t * task_fn); /*! * Run the task associated with an #OS_DEV_TASK() function * * The task will begin execution sometime after or during this call. * * @param task_fn Name of the OS_DEV_TASK() function to be scheduled. * * @return void */ void os_dev_schedule_task(os_task_fn_t * task_fn); /*! * Make sure that task is no longer running and will no longer run. * * This function will not return until both are true. This is useful when * shutting down a driver. * * @param task_fn Name of the OS_DEV_TASK() funciton to be stopped. * */ void os_stop_task(os_task_fn_t * task_fn); /*! * Delay some number of microseconds * * Note that this is a busy-loop, not a suspension of the task/process. * * @param msecs The number of microseconds to delay * * @return void */ void os_mdelay(unsigned long msecs); /*! * Calculate virtual address from physical address * * @param pa Physical address * * @return virtual address * * @note this assumes that addresses are 32 bits wide */ void *os_va(uint32_t pa); /*! * Calculate physical address from virtual address * * * @param va Virtual address * * @return physical address * * @note this assumes that addresses are 32 bits wide */ uint32_t os_pa(void *va); /*! * Allocate and initialize a lock, returning a lock handle. * * The lock state will be initialized to 'unlocked'. * * @return A lock handle, or NULL if an error occurred. */ os_lock_t os_lock_alloc_init(void); /*! * Acquire a lock. * * This function should only be called from an interrupt service routine. * * @param lock_handle A handle to the lock to acquire. * * @return void */ void os_lock(os_lock_t lock_handle); /*! * Unlock a lock. Lock must have been acquired by #os_lock(). * * @param lock_handle A handle to the lock to unlock. * * @return void */ void os_unlock(os_lock_t lock_handle); /*! * Acquire a lock in non-ISR context * * This function will spin until the lock is available. * * @param lock_handle A handle of the lock to acquire. * @param context Place to save the before-lock context * * @return void */ void os_lock_save_context(os_lock_t lock_handle, os_lock_context_t context); /*! * Release a lock in non-ISR context * * @param lock_handle A handle of the lock to release. * @param context Place where before-lock context was saved. * * @return void */ void os_unlock_restore_context(os_lock_t lock_handle, os_lock_context_t context); /*! * Deallocate a lock handle. * * @param lock_handle An #os_lock_t that has been allocated. * * @return void */ void os_lock_deallocate(os_lock_t lock_handle); /*! * Determine process handle * * The process handle of the current user is returned. * * @return A handle on the current process. */ os_process_handle_t os_get_process_handle(); /*! * Send a signal to a process * * @param proc A handle to the target process. * @param sig The POSIX signal to send to that process. */ void os_send_signal(os_process_handle_t proc, int sig); /*! * Get some random bytes * * @param buf The location to store the random data. * @param count The number of bytes to store. * * @return void */ void os_get_random_bytes(void *buf, unsigned count); /*! * Go to sleep on an object. * * Example: code = os_sleep(my_queue, available_count == 0, 0); * * @param object The object on which to sleep * @param condition An expression to check for sleep completion. Must be * coded so that it can be referenced more than once inside * macro, i.e., no ++ or other modifying expressions. * @param atomic Non-zero if sleep must not return until condition. * * @return error code -- OK or sleep interrupted?? */ os_error_code os_sleep(os_sleep_object_t object, unsigned condition, unsigned atomic); /*! * Wake up whatever is sleeping on sleep object * * @param object The object on which things might be sleeping * * @return none */ void os_wake_sleepers(os_sleep_object_t object); /*! @} *//* dkops */ /***************************************************************************** * Function-signature-generating macros *****************************************************************************/ /*! * @defgroup drsigs Driver Function Signatures * * These macros will define the entry point signatures for interrupt handlers; * driver initialization and shutdown; device open/close; etc. They are to be * used whenever the Kernel will call into the Driver. They are not * appropriate for driver calls to other routines in the driver. * * There are three versions of each macro for a given Driver Entry Point. The * first version is used to define a function and its implementation in the * driver.c file, e.g. #OS_DEV_INIT(). * * The second form is used whenever a forward declaration (prototype) is * needed. It has the letters @c _DCL appended to the name of the definition * function. These are not otherwise mentioned in this documenation. * * There is a third form used when a reference to a function is required, for * instance when passing the routine as a pointer to a function. It has the * letters @c _REF appended to the name of the definition function * (e.g. DEV_IOCTL_REF). * * Note that these two extra forms are required because of the possibility of * having an invisible 'wrapper function' created by the os-specific header * file which would need to be invoked by the operating system, and which in * turn would invoke the generic function. * * Example: * * (in a header file) * @code * OS_DEV_INIT_DCL(widget_init); * OS_DEV_ISR_DCL(widget_isr); * @endcode * * (in an implementation file) * @code * OS_DEV_INIT(widget, widget_init) * { * * os_register_interrupt("widget", WIDGET_IRQ, OS_DEV_ISR_REF(widget_isr)); * * os_dev_init_return(OS_RETURN_NO_ERROR_S); * } * * OS_DEV_ISR(widget_isr) * { * os_dev_isr_return(TRUE); * } * @endcode */ /*! @addtogroup drsigs */ /*! @{ */ /*! * Define a function which will handle device initialization * * This is tne driver initialization routine. This is normally where the * part would be initialized; queues, locks, interrupts handlers defined; * long-term dynamic memory allocated for driver use; etc. * * @param function_name The name of the portable initialization function. * * @return A call to #os_dev_init_return() * */ #define OS_DEV_INIT(function_name) /*! * Define a function which will handle device shutdown * * This is the reverse of the #OS_DEV_INIT() routine. * * @param function_name The name of the portable driver shutdown routine. * * @return A call to #os_dev_shutdown_return() */ #define OS_DEV_SHUTDOWN(function_name) /*! * Define a function which will open the device for a user. * * @param function_name The name of the driver open() function * * @return A call to #os_dev_open_return() */ #define OS_DEV_OPEN(function_name) /*! * Define a function which will handle a user's ioctl() request * * @param function_name The name of the driver ioctl() function * * @return A call to #os_dev_ioctl_return() */ #define OS_DEV_IOCTL(function_name) /*! * Define a function which will handle a user's read() request * * @param function_name The name of the driver read() function * * @return A call to #os_dev_read_return() */ #define OS_DEV_READ(function_name) /*! * Define a function which will handle a user's write() request * * @param function_name The name of the driver write() function * * @return A call to #os_dev_write_return() */ #define OS_DEV_WRITE(function_name) /*! * Define a function which will handle a user's mmap() request * * The mmap() function requests the driver to map some memory into user space. * * @todo Determine what support functions are needed for mmap() handling. * * @param function_name The name of the driver mmap() function * * @return A call to #os_dev_mmap_return() */ #define OS_DEV_MMAP(function_name) /*! * Define a function which will close the device - opposite of OS_DEV_OPEN() * * @param function_name The name of the driver close() function * * @return A call to #os_dev_close_return() */ #define OS_DEV_CLOSE(function_name) /*! * Define a function which will handle an interrupt * * No arguments are available to the generic function. It must not invoke any * OS functions which are illegal in a ISR. It gets no parameters, and must * have a call to #os_dev_isr_return() instead of any/all return statements. * * Example: * @code * OS_DEV_ISR(widget, widget_isr, WIDGET_IRQ_NUMBER) * { * os_dev_isr_return(1); * } * @endcode * * @param function_name The name of the driver ISR function * * @return A call to #os_dev_isr_return() */ #define OS_DEV_ISR(function_name) /*! * Define a function which will operate as a background task / bottom half. * * The function implementation must be structured in the following manner: * @code * OS_DEV_TASK(widget_task) * { * OS_DEV_TASK_SETUP(widget_task); * * while OS_DEV_TASK_CONDITION(widget_task) } * * }; * } * @endcode * * @todo In some systems the OS_DEV_TASK_CONDITION() will be an action which * will cause the task to sleep on some event triggered by os_run_task(). In * others, the macro will reference a variable laid down by * OS_DEV_TASK_SETUP() to make sure that the loop is only performed once. * * @param function_name The name of this background task function */ #define OS_DEV_TASK(function_name) /*! @} *//* drsigs */ /*! @defgroup dclsigs Routines to declare Driver Signature routines * * These macros drop prototypes suitable for forward-declaration of * @ref drsigs "function signatures". */ /*! @addtogroup dclsigs */ /*! @{ */ /*! * Declare prototype for the device initialization function * * @param function_name The name of the portable initialization function. */ #define OS_DEV_INIT_DCL(function_name) /*! * Declare prototype for the device shutdown function * * @param function_name The name of the portable driver shutdown routine. * * @return A call to #os_dev_shutdown_return() */ #define OS_DEV_SHUTDOWN_DCL(function_name) /*! * Declare prototype for the open() function. * * @param function_name The name of the driver open() function * * @return A call to #os_dev_open_return() */ #define OS_DEV_OPEN_DCL(function_name) /*! * Declare prototype for the user's ioctl() request function * * @param function_name The name of the driver ioctl() function * * @return A call to #os_dev_ioctl_return() */ #define OS_DEV_IOCTL_DCL(function_name) /*! * Declare prototype for the function a user's read() request * * @param function_name The name of the driver read() function */ #define OS_DEV_READ_DCL(function_name) /*! * Declare prototype for the user's write() request function * * @param function_name The name of the driver write() function */ #define OS_DEV_WRITE_DCL(function_name) /*! * Declare prototype for the user's mmap() request function * * @param function_name The name of the driver mmap() function */ #define OS_DEV_MMAP_DCL(function_name) /*! * Declare prototype for the close function * * @param function_name The name of the driver close() function * * @return A call to #os_dev_close_return() */ #define OS_DEV_CLOSE_DCL(function_name) /*! * Declare prototype for the interrupt handling function * * @param function_name The name of the driver ISR function */ #define OS_DEV_ISR_DCL(function_name) /*! * Declare prototype for a background task / bottom half function * * @param function_name The name of this background task function */ #define OS_DEV_TASK_DCL(function_name) /*! @} *//* dclsigs */ /***************************************************************************** * Functions for Returning Values from Driver Signature routines *****************************************************************************/ /*! * @defgroup retfns Functions to Return Values from Driver Signature routines */ /*! @addtogroup retfns */ /*! @{ */ /*! * Return from the #OS_DEV_INIT() function * * @param code An error code to report success or failure. * */ void os_dev_init_return(os_error_code code); /*! * Return from the #OS_DEV_SHUTDOWN() function * * @param code An error code to report success or failure. * */ void os_dev_shutdown_return(os_error_code code); /*! * Return from the #OS_DEV_ISR() function * * The function should verify that it really was supposed to be called, * and that its device needed attention, in order to properly set the * return code. * * @param code non-zero if interrupt handled, zero otherwise. * */ void os_dev_isr_return(int code); /*! * Return from the #OS_DEV_OPEN() function * * @param code An error code to report success or failure. * */ void os_dev_open_return(os_error_code code); /*! * Return from the #OS_DEV_IOCTL() function * * @param code An error code to report success or failure. * */ void os_dev_ioctl_return(os_error_code code); /*! * Return from the #OS_DEV_READ() function * * @param code Number of bytes read, or an error code to report failure. * */ void os_dev_read_return(os_error_code code); /*! * Return from the #OS_DEV_WRITE() function * * @param code Number of bytes written, or an error code to report failure. * */ void os_dev_write_return(os_error_code code); /*! * Return from the #OS_DEV_MMAP() function * * @param code Number of bytes written, or an error code to report failure. * */ void os_dev_mmap_return(os_error_code code); /*! * Return from the #OS_DEV_CLOSE() function * * @param code An error code to report success or failure. * */ void os_dev_close_return(os_error_code code); /*! * Start the #OS_DEV_TASK() function * * In some implementations, this could be turned into a label for * the os_dev_task_return() call. * * For a more portable interface, should this take the sleep object as an * argument??? * * @return none */ void os_dev_task_begin(void); /*! * Return from the #OS_DEV_TASK() function * * In some implementations, this could be turned into a sleep followed * by a jump back to the os_dev_task_begin() call. * * @param code An error code to report success or failure. * */ void os_dev_task_return(os_error_code code); /*! @} *//* retfns */ /***************************************************************************** * Functions/Macros for accessing arguments from Driver Signature routines *****************************************************************************/ /*! @defgroup drsigargs Functions for Getting Arguments in Signature functions * */ /* @addtogroup @drsigargs */ /*! @{ */ /*! * Check whether user is requesting read (permission) on the file/device. * Usable in #OS_DEV_OPEN(), #OS_DEV_CLOSE(), #OS_DEV_IOCTL(), #OS_DEV_READ() * and #OS_DEV_WRITE() routines. */ int os_dev_is_flag_read(void); /*! * Check whether user is requesting write (permission) on the file/device. * Usable in #OS_DEV_OPEN(), #OS_DEV_CLOSE(), #OS_DEV_IOCTL(), #OS_DEV_READ() * and #OS_DEV_WRITE() routines. */ int os_dev_is_flag_write(void); /*! * Check whether user is requesting non-blocking I/O. Usable in * #OS_DEV_OPEN(), #OS_DEV_CLOSE(), #OS_DEV_IOCTL(), #OS_DEV_READ() and * #OS_DEV_WRITE() routines. * * @todo Specify required behavior when nonblock is requested and (sufficient?) * data are not available to fulfill the request. * */ int os_dev_is_flag_nonblock(void); /*! * Determine which major device is being accessed. Usable in #OS_DEV_OPEN() * and #OS_DEV_CLOSE(). */ int os_dev_get_major(void); /*! * Determine which minor device is being accessed. Usable in #OS_DEV_OPEN() * and #OS_DEV_CLOSE(). */ int os_dev_get_minor(void); /*! * Determine which operation the user wants performed. Usable in * #OS_DEV_IOCTL(). * * @return Value of the operation. * * @todo Define some generic way to define the individual operations. */ unsigned os_dev_get_ioctl_op(void); /*! * Retrieve the associated argument for the desired operation. Usable in * #OS_DEV_IOCTL(). * * @return A value which can be cast to a struct pointer or used as * int/long. */ os_dev_ioctl_arg_t os_dev_get_ioctl_arg(void); /*! * Determine the requested byte count. This should be the size of buffer at * #os_dev_get_user_buffer(). Usable in OS_DEV_READ() and OS_DEV_WRITE() * routines. * * @return A count of bytes */ unsigned os_dev_get_count(void); /*! * Get the pointer to the user's data buffer. Usable in OS_DEV_READ(), * OS_DEV_WRITE(), and OS_DEV_MMAP() routines. * * @return Pointer to user buffer (in user space). See #os_copy_to_user() * and #os_copy_from_user(). */ void *os_dev_get_user_buffer(void); /*! * Get the POSIX flags field for the associated open file. Usable in * OS_DEV_READ(), OS_DEV_WRITE(), and OS_DEV_IOCTL() routines. * * @return The flags associated with the file. */ unsigned os_dev_get_file_flags(void); /*! * Set the driver's private structure associated with this file/open. * * Generally used during #OS_DEV_OPEN(). May also be used during * #OS_DEV_READ(), #OS_DEV_WRITE(), #OS_DEV_IOCTL(), #OS_DEV_MMAP(), and * #OS_DEV_CLOSE(). See also #os_dev_get_user_private(). * * @param struct_p The driver data structure to associate with this user. */ void os_dev_set_user_private(void *struct_p); /*! * Get the driver's private structure associated with this file. * * May be used during #OS_DEV_OPEN(), #OS_DEV_READ(), #OS_DEV_WRITE(), * #OS_DEV_IOCTL(), #OS_DEV_MMAP(), and #OS_DEV_CLOSE(). See * also #os_dev_set_user_private(). * * @return The driver data structure to associate with this user. */ void *os_dev_get_user_private(void); /*! * Get the IRQ associated with this call to the #OS_DEV_ISR() function. * * @return The IRQ (integer) interrupt number. */ int os_dev_get_irq(void); /*! @} *//* drsigargs */ /***************************************************************************** * Functions for Generating References to Driver Routines *****************************************************************************/ /*! * @defgroup drref Functions for Generating References to Driver Routines * * These functions will most likely be implemented as macros. They are a * necessary part of the portable API to guarantee portability. The @c symbol * type in here is the same symbol passed to the associated * signature-generating macro. * * These macros must be used whenever referring to a * @ref drsigs "driver signature function", for instance when storing or * passing a pointer to the function. */ /*! @addtogroup drref */ /*! @{ */ /*! * Generate a reference to an #OS_DEV_INIT() function * * @param function_name The name of the init function being referenced. * * @return A reference to the function */ os_init_function_t OS_DEV_INIT_REF(symbol function_name); /*! * Generate a reference to an #OS_DEV_SHUTDOWN() function * * @param function_name The name of the shutdown function being referenced. * * @return A reference to the function */ os_shutdown_function_t OS_DEV_SHUTDOWN_REF(symbol function_name); /*! * Generate a reference to an #OS_DEV_OPEN() function * * @param function_name The name of the open function being referenced. * * @return A reference to the function */ os_user_function_t OS_DEV_OPEN_REF(symbol function_name); /*! * Generate a reference to an #OS_DEV_CLOSE() function * * @param function_name The name of the close function being referenced. * * @return A reference to the function */ os_user_function_t OS_DEV_CLOSE_REF(symbol function_name); /*! * Generate a reference to an #OS_DEV_READ() function * * @param function_name The name of the read function being referenced. * * @return A reference to the function */ os_user_function_t OS_DEV_READ_REF(symbol function_name); /*! * Generate a reference to an #OS_DEV_WRITE() function * * @param function_name The name of the write function being referenced. * * @return A reference to the function */ os_user_function_t OS_DEV_WRITE_REF(symbol function_name); /*! * Generate a reference to an #OS_DEV_IOCTL() function * * @param function_name The name of the ioctl function being referenced. * * @return A reference to the function */ os_user_function_t OS_DEV_IOCTL_REF(symbol function_name); /*! * Generate a reference to an #OS_DEV_MMAP() function * * @param function_name The name of the mmap function being referenced. * * @return A reference to the function */ os_user_function_t OS_DEV_MMAP_REF(symbol function_name); /*! * Generate a reference to an #OS_DEV_ISR() function * * @param function_name The name of the isr being referenced. * * @return a reference to the function */ os_interrupt_handler_t OS_DEV_ISR_REF(symbol function_name); /*! @} *//* drref */ /*! * Flush and invalidate all cache lines. */ void os_flush_cache_all(void); /*! * Flush a range of addresses from the cache * * @param start Starting virtual address * @param len Number of bytes to flush */ void os_cache_flush_range(void *start, uint32_t len); /*! * Invalidate a range of addresses in the cache * * @param start Starting virtual address * @param len Number of bytes to flush */ void os_cache_inv_range(void *start, uint32_t len); /*! * Clean a range of addresses from the cache * * @param start Starting virtual address * @param len Number of bytes to flush */ void os_cache_clean_range(void *start, uint32_t len); /*! * @example widget.h */ /*! * @example widget.c */ /*! * @example rng_driver.h */ /*! * @example rng_driver.c */ /*! * @example shw_driver.h */ /*! * @example shw_driver.c */ #endif /* DOXYGEN_PORTABLE_OS_DOC */ #endif /* PORTABLE_OS_H */