⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flsystem.c

📁 H3 M-system NAND flash driver in Linux OS, M-DOC driver
💻 C
📖 第 1 页 / 共 2 页
字号:
    total_sems = 0;    /* DiskOnChip H3 devices can be configured to use 8-, 32- or 128-KByte     * window; we assume the worst case here (128-KB).     */    win_size = DOCH_MEM_WIN_SIZE_128KB /* or DOCH_MEM_WIN_SIZE_8KB */;     for (iSoc = 0; iSoc < FL_SOCKETS; iSoc++)        TffsMapMem (&tffsInfo.sockets[iSoc], tffs_addr[iSoc], win_size);    /* We are not doing 'resume' after previous power 'suspend', but rather     * a full scale board initialization, hence FALSE flag below.     */    if( tffsarch_init(FALSE) == 0 )        PrintkWarning("tffsarch_init error");}void  LnxSysfunRelease ( void ){    int i;    for (i = 0; i < FL_SOCKETS; i++)        TffsUnmapMem (&tffsInfo.sockets[i]);    total_sems = 0;    TffsHWRelease ();}/*-----------------------------------------------------------------------* *                                                                       * *                       f l C r e a t e M u t e x                       * *                                                                       * * Create mutex.                   .                                     * *                                                                       * * Parameters:                                                           * *      mutex         ID of newly created sempahore will be stored here  * *                                                                       * * Returns:                                                              * *      flOK if successful otherwise respective error code               * *                                                                       * *-----------------------------------------------------------------------*/FLStatus  flCreateMutex (FLMutex * mutex){    if (total_sems >= (sizeof(sems) / sizeof(sems[0])))    {        PrintkError("flCreateMutex: error creating mutex");        return flNotEnoughMemory;    }    /* initialize next available semaphore to 'available' state */    sema_init (&sems[total_sems], 1);    *mutex = (FLMutex) total_sems++;    return flOK;}/*-----------------------------------------------------------------------* *                                                                       * *                       f l T a k e M u t e x                           * *                                                                       * * Called to aquire the mutex.                                           * *                                                                       * * Parameters:                                                           * *      mutex           identifies mutex to release                      * *                                                                       * * Returns:                                                              * *      always TRUE                                                      * *                                                                       * *-----------------------------------------------------------------------*/FLBoolean  flTakeMutex (FLMutex * mutex){    register struct semaphore * psem = &sems[ (int)(*mutex) ];    /* put caller to sleep until semaphore is available */    if( down_interruptible(psem) != 0 )    {        /* Semaphore still isn't available - down_interruptible() returned         * because caller was waken up by signal. We must abort TrueFFS call.         */        return FALSE;    }    /* semaphore has been taken; TrueFFS call can proceed now */    return TRUE;}/*-----------------------------------------------------------------------* *                                                                       * *                       f l F r e e M u t e x                           * *                                                                       * * Called to release the mutex.                                          * *                                                                       * * Parameters:                                                           * *      mutex           identifies mutex to release                      * *                                                                       * *-----------------------------------------------------------------------*/void  flFreeMutex (FLMutex * mutex){    register struct semaphore * psem = &sems[ (int)(*mutex) ];    /* release semaphore */    up (psem);}/*-----------------------------------------------------------------------* *                                                                       * *                       f l D e l e t e M u t e x                       * *                                                                       * * Called to destroy the mutex and free all associated resources.        * *                                                                       * * Parameters:                                                           * *      mutex           identifies mutex to destroy                      * *                                                                       * *-----------------------------------------------------------------------*/void  flDeleteMutex (FLMutex * mutex){    /* just in case some thread(s) are still sleeping on this semaphore */    flFreeMutex (mutex);}/*-----------------------------------------------------------------------* *                                                                       * *                       f l B u i l d G e o m e t r y                   * *                                                                       * * This routine calculates cylinder/head/sector geometry based on the    * * number of sectors on the disk.                                        * *                                                                       * * Parameters:                                                           * *      sectors         total sectors on disk                            * *      cyl             pointer to number of cylinders                   * *      heads           pointer to number of heads                       * *      sec_per_track   pointer to number of sectors per track           * *      oldFormat       ignored                                          * *      wirHandle       ignored                                          * *                                                                       * *-----------------------------------------------------------------------*/void flBuildGeometry ( unsigned long   sectors,                        unsigned long * cyl,                       unsigned long * heads,                       unsigned long * sec_per_track,                       unsigned char   oldFormat,                       unsigned short  wIrHandle ){    DeviceInfo  * pdisk;    register int  i;    for (i = 0; i < (sizeof(tffsInfo.ppDevices) / sizeof(tffsInfo.ppDevices[0])); i++)    {        if ((pdisk = tffsInfo.ppDevices[i]) == NULL)            return;        /* The 'wIrHandle' argument is the internal TrueFFS handle which is         * different from TrueFFS handle stored in DeviceInfo.bHandle, and         * passed to TrueFFS API routines.          */        if (pdisk->dwSize == sectors) /* was (pdisk->bHandle == wIrHandle) */        {            if (cyl           != NULL) *cyl           = pdisk->wCyl;            if (heads         != NULL) *heads         = pdisk->bHead;            if (sec_per_track != NULL) *sec_per_track = pdisk->bSect;            return;        }    }}/*-----------------------------------------------------------------------* *                                                                       * *                 i r q _ w a i t _ t i m e d _ o u t                   * *                                                                       * * This routine is called when DiskOnChip interrupt gets lost, and       * * watchdog timer gets activated. It prevents driver from hanging up in  * * such cases by posting a semaphore that socket's I/O thread is waiting * * for.                                                                  * *                                                                       * * Parameters:                                                           * *      arg           pointer to semaphore                               * *                                                                       * *-----------------------------------------------------------------------*/staticvoid irq_wait_timed_out ( unsigned long arg ){    profiling[5]++;    /* Since this routine is running, it means that DiskOnChip interrupt     * got lost (or delayed for too long). To prevent socket's I/O thread     * from hanging up, we post semaphore that it is waiting for.     */    up ((struct semaphore *)arg);}/*-----------------------------------------------------------------------* *                                                                       * *                     f l _ t f f s _ s l e e p                         * *                                                                       * * This routine is called right after starting flash 'write' or 'erase'  * * operation on DiskOnChip. These operations usually take around 700     * * ('write') or 3000 ('erase') microseconds to complete. This routine    * * might yield the CPU and cause task switch.                            * *                                                                       * * Parameters:                                                           * *      handle        TrueFFS handle (only lower 4 bits are used)        * *      microseconds  expected average duration of flash operation       * *                                                                       * *-----------------------------------------------------------------------*/void  fl_tffs_sleep ( unsigned int   handle,                       unsigned long  microseconds ){#ifdef TFFS_USE_SLEEP    int socNo = (int)(handle & 0xf);  /* extract socket # from TrueFFS handle */    static int _counter = 0;    if (tffsInfo.sockets[socNo].io_thread_state != 1)    {        /* DiskOnChip driver is being uninstalled, or power-suspended, or is         * power-resuming. In either of these cases, we want to process all         * outstanding I/O requests as quickly as possible; therefore we         * will not sleep.         */        return;    }    if (tffs_irq < 0)  /* DiskOnChip R/B interrupts are not used */    {        if (++_counter > tffs_skip_sleeps)	{            /* Once in a while (once in 'tffs_skip_sleeps' calls to this routine)             * we yield CPU and put DiskOnChip driver to sleep, to give chance             * to other tasks to run. Note that this negatively impacts             * DiskOnChip's 'write' performance.             */            unsigned long jiffies_to_sleep = (HZ * microseconds) / 1000000;#if 0            if (jiffies_to_sleep == 0)                jiffies_to_sleep = 1;#endif            /* yield CPU and sleep */            set_current_state (TASK_INTERRUPTIBLE);            schedule_timeout (jiffies_to_sleep);            _counter = 0;	}        else	{            /* TrueFFS will busy-poll DiskOnChip's status register to             * detect completion of flash 'write' and 'erase' operations. This             * improves DiskOnChip's 'write' performance, but also ties up CPU             * for extensive periods of time.             */            return;	}    }    else    /* yield CPU and sleep until waken up by DiskOnChip interrupt */    {        struct timer_list watchdog_timer;        profiling[0]++;        /* To guard ourselves against stray DiskOnChip interrupts,         * we clear tffsInfo.sockets[socNo].sleep_sem sempahore         * before enabling IRQ that DiskOnChip is nonnected to         */        sema_init (&tffsInfo.sockets[socNo].sleep_sem, 0);        tffs_irq_enable (TRUE);        /* To guard ourselves against the case when DiskOnChip interrupt         * will not be generated for some reason, or will get lost, we         * set watchdog timer to wake us up after 30 milliseconds.         */        init_timer (&watchdog_timer);        watchdog_timer.function = irq_wait_timed_out;        watchdog_timer.data     = (unsigned long) &tffsInfo.sockets[socNo].sleep_sem;        watchdog_timer.expires  = jiffies + ((30 * HZ) / 1000);        add_timer (&watchdog_timer);        /* sleep until DiskOnChip interrupt or watchdog timer wakes us up */        down_interruptible (&tffsInfo.sockets[socNo].sleep_sem);        tffs_irq_disable (TRUE);        /* no longer need watchdog timer */        del_timer_sync (&watchdog_timer);    }#endif /* TFFS_USE_SLEEP */}/*-----------------------------------------------------------------------* *                                                                       * *                          d o c h _ s l e e p                          * *                                                                       * * This routine is called numerous times during DiskOnChip H3 'write'    * * operations.                                                           * *                                                                       * * Parameters:                                                           * *      sock          socket # (zero-based)                              * *      microseconds  expected average duration of flash operation       * *                                                                       * *-----------------------------------------------------------------------*/void doch_sleep ( unsigned int  soc,                  unsigned long microseconds ){    extern int   write_requests;    static int __write_requests = 0;       /* If DiskOnChip IRQ is enabled, or if 'tffs_skip_sleeps' set to yeild     * CPU often, we yield CPU.     */     if (tffs_irq >= 0)    {        fl_tffs_sleep (soc, microseconds);    }    else                     {        /* DiskOnChip IRQ is disabled. We yield CPU according to         * 'tffs_skip_sleep' setting, making sure that we do yield CPU         * at least once per I/O 'write' request.         */	if ((tffs_skip_sleeps >= 100) || (write_requests != __write_requests))        {            fl_tffs_sleep (soc, microseconds);        }        __write_requests = write_requests;    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -