/**************************************************************************** *.Copyright (c) 2006 DST Technologies Inc. All Rights Reserved. * * Module: LLD_OSUTIL * * Description: Unified APIs for Lowest Level Driver * * Notes: This module implements APIs to interface with the following * device objects: * - OS specific Utilities * ***************************************************************************/ #include "lld_os.h" #include "lld_local.h" #include /*============================== * Local defines *=============================*/ /* * This returns 1 if the address is from user-address-space * It's used because some of the functions can be called with * args from user-space or from kernel-space memory */ #define FROM_USER_SPACE(addr) (((DS_U32) (addr)) >= PAGE_OFFSET ? 0 : 1) #define PUSH_PID DS_U32 PidSave=current_filp; current_filp=KERNEL_PID; #define POP_PID current_filp=PidSave; /*============================== * Local prototypes *=============================*/ /*============================== * External declarations *=============================*/ extern DS_U32 current_filp; /*^^*************************************************************************** * void lld_delay (milliseconds) * * Description: * Delays execution of caller for some milliseconds * This should NOT be used from interrupt handlers ! * * Entry : number of milliseconds to delay * * Return: nothing * **************************************************************************^^*/ void lld_delay (DS_U32 millisec) { PUSH_PID; #if KERNEL_2_4_0 current->state = TASK_INTERRUPTIBLE; schedule_timeout ((HZ / 1000) * millisec); #elif 1 current->state = TASK_INTERRUPTIBLE; schedule_timeout ((HZ / 1000) * millisec); #else current->timeout = (HZ / 1000) * millisec; current->state = TASK_INTERRUPTIBLE; schedule (); current->timeout = 0; #endif POP_PID; } /*^^*************************************************************************** * void lld_os_disable_ints (void) * * Description: * disables system interrupts * * Entry : none * * Return: previous interrupt flag state * **************************************************************************^^*/ DS_U32 lld_os_disable_ints (void) { DS_U32 flags; #if KERNEL_2_4_0 save_flags(flags); cli (); #else local_save_flags(flags); local_irq_disable (); #endif return (flags); } /*^^*************************************************************************** * void lld_os_restore_ints (DS_U32 flags) * * Description: * restores interrupt state * * Entry : none * * Return: none * **************************************************************************^^*/ void lld_os_restore_ints (DS_U32 flags) { #if KERNEL_2_4_0 restore_flags(flags); #else local_irq_restore(flags); #endif } /*^^*************************************************************************** * void lld_os_enable_ints (void) * * Description: * Enable interrupts * * Entry : none * * Return: none * **************************************************************************^^*/ void lld_os_enable_ints (void) { #if KERNEL_2_4_0 sti(); #else local_irq_enable(); #endif } /*^^*************************************************************************** * void* lld_os_malloc (DS_U32 cbsize) * * Description: * allocates a block of kernel memory * * Entry : cbsize = size in bytes * * Return: pointer to allocated kernel memory block * **************************************************************************^^*/ void* lld_os_malloc (DS_U32 cbsize) { return kmalloc (cbsize, GFP_KERNEL); } /*^^*************************************************************************** * void lld_os_free (void *pmemory) * * Description: * frees a previously allocated block of kernel memory * * Entry : pointer to allocated kernel memory block * * Return: none * **************************************************************************^^*/ void lld_os_free (void *pmemory) { kfree (pmemory); } /*^^*************************************************************************** * void lld_os_copy_from_user (DS_S8 *pdest, DS_S8* psrc, DS_U32 cbsize) * * Description: * copys the contents of user memory to kernel memory * * Entry : pdest = kernel mode destination pointer * psrc = user mode source pointer * cbsize = size in bytes * * Return: none * **************************************************************************^^*/ void lld_os_copy_from_user (DS_S8 *pdest, DS_S8* psrc, DS_U32 cbsize) { if (FROM_USER_SPACE(psrc)) { copy_from_user (pdest, psrc, cbsize); } else { memcpy (pdest, psrc, cbsize); } } /*^^*************************************************************************** * void lld_os_copy_to_user (DS_S8 *pdest, DS_S8* psrc, DS_U32 cbsize) * * Description: * copys the contents of kernel memory to user memory * * Entry : pdest = user mode destination pointer * psrc = kernel mode source pointer * cbsize = size in bytes * * Return: none * **************************************************************************^^*/ void lld_os_copy_to_user (DS_S8 *pdest, DS_S8* psrc, DS_U32 cbsize) { if (FROM_USER_SPACE(pdest)) { copy_to_user (pdest, psrc, cbsize); } else { memcpy (pdest, psrc, cbsize); } } /*^^*************************************************************************** * DS_BOOL lld_os_init_lock (DS_U32 lock, DS_U32 Init) * * Description: * initialize os specific semaphore type object * * Entry : lock = Pointer to os specific semaphore id * Init = initialization value * * Return: _TRUE_ or _FALSE_ * **************************************************************************^^*/ DS_BOOL lld_os_init_lock (DS_U32 lock, DS_U32 Init) { sema_init ((struct semaphore*)lock, Init); return (_TRUE_); } /*^^*************************************************************************** * DS_BOOL lld_os_get_lock (DS_U32 lock) * * Description: * locks an os specific semaphore type object * * Entry : lock = os specific semaphore id * * Return: _TRUE_ or _FALSE_ * **************************************************************************^^*/ DS_BOOL lld_os_get_lock (DS_U32 lock) { PUSH_PID; down((struct semaphore*)lock); POP_PID; return (_TRUE_); } /*^^*************************************************************************** * lld_os_release_lock * * Description: * unlocks an os specific semaphore type object * * Entry : lock = os specific semaphore id * * Return: _TRUE_ or _FALSE_ * **************************************************************************^^*/ DS_BOOL lld_os_release_lock (DS_U32 lock) { up((struct semaphore*)lock); return (_TRUE_); } /*^^*************************************************************************** * lld_os_get_usermode_process_id * * Description: * get current user mode process id. * * Entry : none * * Return: current user mode process id * **************************************************************************^^*/ DS_U32 lld_os_get_usermode_process_id (void) { return ((DS_U32)current_filp); } /*^^*************************************************************************** * DS_BOOL lld_os_signal_detected (void) * * Description: * * Entry: None * * Return: _TRUE_ if the current task received an OS signal (e.g. Ctrl-C) * * Notes: * **************************************************************************^^*/ DS_BOOL lld_os_signal_detected (void) { return (signal_pending(current)); } /*^^*************************************************************************** * DS_BOOL lld_check_wait_q (WAIT_Q *WaitQPtr) * * Description: * * Entry: WaitQPtr = Wait queue pointer * * Return: _TRUE_ if the queue contains any sleeping tasks * * Notes: * **************************************************************************^^*/ DS_BOOL lld_check_wait_q (WAIT_Q *WaitQPtr) { return (waitqueue_active(WaitQPtr)); } /*^^*************************************************************************** * void lld_wait_for_interrupt (WAIT_Q *WaitQPtr) * * Description: * Enable interrupts and wait on WaitQPtr for wake up * * Entry: WaitQPtr = Wait queue pointer * * Return: Interrupt occured * * Notes: Interrupts can be disabled before calling this function * **************************************************************************^^*/ void lld_wait_for_interrupt (WAIT_Q *WaitQPtr) { DECLARE_WAITQUEUE(wait, current); PUSH_PID; add_wait_queue(WaitQPtr, &wait); __set_current_state(TASK_INTERRUPTIBLE); lld_os_enable_ints(); schedule(); remove_wait_queue(WaitQPtr, &wait); set_current_state(TASK_RUNNING); POP_PID; } /*^^*************************************************************************** * DS_U32 lld_init_wait_q (WAIT_Q *WaitQPtr) * * Description: Initialize wait queue * * Entry: WaitQPtr = Wait queue pointer * * Return: 0 * * Notes: * **************************************************************************^^*/ DS_U32 lld_init_wait_q (WAIT_Q *WaitQPtr) { #if 1 init_waitqueue_head (WaitQPtr); #else *WaitQPtr = NULL; #endif return (0); } /*^^*************************************************************************** * DS_U32 lld_wait_on_q (WAIT_Q *WaitQPtr) * * Description: Wait on queue for wake up signal * * Entry: WaitQPtr = Wait queue pointer * * Return: Wake up signal received * * Notes: * **************************************************************************^^*/ DS_U32 lld_wait_on_q (WAIT_Q *WaitQPtr) { PUSH_PID; interruptible_sleep_on (WaitQPtr); POP_PID; return (0); } /*^^*************************************************************************** * DS_U32 lld_timeout_wait_on_q (WAIT_Q *WaitQPtr, DS_U32 TimeOut) * * Description: Wait on queue with timeout * * Entry: WaitQPtr = Wait queue pointer * * Return: * * Notes: * **************************************************************************^^*/ DS_U32 lld_timeout_wait_on_q (WAIT_Q *WaitQPtr, DS_U32 TimeOut) { DS_U32 i; PUSH_PID; i = (DS_U32)(interruptible_sleep_on_timeout (WaitQPtr, TimeOut)); POP_PID; return (i); } /*^^*************************************************************************** * DS_U32 lld_wakeup_wait_q (WAIT_Q *WaitQPtr) * * Description: Wake up waiting interruptible taks in a queue * * Entry: WaitQPtr = Wait queue pointer * * Return: * * Notes: * **************************************************************************^^*/ DS_U32 lld_wakeup_wait_q (WAIT_Q *WaitQPtr) { PUSH_PID; wake_up_interruptible (WaitQPtr); POP_PID; return (0); } /*^^*************************************************************************** * DS_U32 lld_force_wakeup_wait_q (WAIT_Q *WaitQPtr) * * Description: Wake up any tasks in a queue * * Entry: WaitQPtr = Wait queue pointer * * Return: * * Notes: * **************************************************************************^^*/ DS_U32 lld_force_wakeup_wait_q (WAIT_Q *WaitQPtr) { PUSH_PID; wake_up (WaitQPtr); POP_PID; return (0); }