📄 flsystem.c
字号:
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 + -