📄 id1_buffer.c
字号:
/***************************************************************************
** File name : id1_buffer.c
** Author : x.cheng
** Create date :
**
** Comment:
** this file implements the buffer-cache functions.
** Race-conditions have been avoided by NEVER letting a interrupt change
** a buffer (except for the data, of course), but instead letting the
** caller do it.
** NOTE! As interrupts can wake up a caller, some cli-sti sequences
** are needed to check for sleep-on-calls.
** These should be extremely quick, though (I hope).
**
** Revisions:
** $Log: id1_buffer.c,v $
** Revision 1.4 2005/08/19 14:56:43 x.cheng
** bug fixe, buffer range changed
**
** Revision 1.3 2005/08/02 15:37:43 x.cheng
** bug fixing~~~~~~~~~~~~~~~~~~~~
**
** Revision 1.2 2005/07/27 16:00:37 x.cheng
** change include path to newer....
**
** Revision 1.1.1.1 2005/07/27 06:53:15 x.cheng
** add into repositories
**
**
***************************************************************************/
#include "const.h"
#include "type.h"
#include "stdarg.h"
#include "..\..\Inc\i386\io.h"
#include "..\..\Inc\i386\system.h"
#include "..\..\Inc\i386\x86.h"
#include "..\..\Inc\i386\map.h"
#include "..\..\inc\ide.h"
#include "..\..\inc\dma.h"
#include "..\..\inc\mts.h"
#include "..\..\inc\tui.h"
#include "..\..\inc\debug.h"
#include "..\inc\def_ide.h"
/* debug preprocessor instrument
#ifdef _DEBUG__
#ifdef _DEBUG_IDE__
#endif
#endif
***************************/
/***********extern variable***************/
/***********global variable***************/
unsigned long g_ulNrOfBlocks = 0;
ts_BufferBlock* g_apstHashTable[NR_HASH]; //NR_HASH = 307项
//local...
static ts_BufferBlock* g_pstFreeList;
static ts_Task* g_pstBufferWaitTask;
/************local function prototype**************/
//hash函数
#define _iHashFunction(iDevice, iBlock) \
( ((unsigned)(iDevice^iBlock)) % NR_HASH )
//hash表项的计算宏定义。
#define pstHash(iDevice, iBlock) \
g_apstHashTable[_iHashFunction(iDevice, iBlock)]
static void Id1WaitOnBuffer(ts_BufferBlock* pstBlock);
static ts_BufferBlock* pstId1FindBuffer(int iDevice, int iBlock);
static inline void Id1RemoveFromQueue( ts_BufferBlock *pstBlock);
static inline void Id1InsertToQueue( ts_BufferBlock *pstBlock);
/************************************************************
*************************************************************
** Function Name: Id1BufferInitialize
** Author: x.cheng
**
** Comment:
** 初始化缓冲区,缓冲区范围:KernelEnd_ -- DMA_MEMORY_END
** 从KernelEnd_开始,利用ts_BufferBlock结构管理整个缓冲区。
**
** List of parameters:
** no
**
** Return value:
** no
**
** Revisions:
**
*************************************************************
*************************************************************/
extern unsigned long KernelEnd_;
void Id1BufferInitialize(void)
{
ts_BufferBlock *pstBlock = (ts_BufferBlock *)KERNEL_FREE_MEMORY_START;
unsigned char *pucAddress = (unsigned char*)(DMA_MEMORY_END);
int i;
#ifdef _DEBUG__
#ifdef _DEBUG_IDE__
kprintf("\nBuffer from [%p] to [%p]\n", pstBlock, pucAddress);
#endif
#endif
while ( (pucAddress -= BUFFER_BLOCK_SIZE) >= ((unsigned char*)(pstBlock+1)) ) {
// refer to drv/inc/def_ide.h for detail comment.
pstBlock->uiDevice = 0;
pstBlock->ucDirty = 0;
pstBlock->ucRefers = 0;
pstBlock->ucLocked = 0;
pstBlock->ucUpToDate = 0;
pstBlock->pstWaitTask = NULL;
pstBlock->pstPrev = NULL;
pstBlock->pstNext = NULL;
pstBlock->pucBlock = pucAddress;
pstBlock->pstPrevFree = pstBlock-1; //(1)some bug...
pstBlock->pstNextFree = pstBlock+1;
pstBlock ++;
g_ulNrOfBlocks ++;
}
pstBlock --;
g_pstFreeList = (ts_BufferBlock *)KERNEL_FREE_MEMORY_START;
g_pstFreeList->pstPrevFree = pstBlock; //这里纠正了(1)处产生的bug
pstBlock->pstNextFree = g_pstFreeList;
#ifdef _DEBUG__
#ifdef _DEBUG_IDE__
kprintf("number of bufferblock= %ld, freelist from [%p] to [%p]\n", g_ulNrOfBlocks, g_pstFreeList, pstBlock);
#endif
#endif
for(i=0; i<NR_HASH; i++) {
g_apstHashTable[i] = NULL;
}
}
/************************************************************
*************************************************************
** Function Name: Id1BufferRead
** Author: x.cheng
**
** Comment:
** reads a specified block and returns the buffer
** that contains it. It returns NULL if the block was unreadable.
**
** List of parameters:
** iDevice - which device.
** iBlock - which block.
**
** Return value:
** ts_BufferBlock*
**
** Revisions:
**
*************************************************************
*************************************************************/
ts_BufferBlock* pstId1BufferRead(int iDevice, int iBlock)
{
ts_BufferBlock* pstBlock;
#ifdef _DEBUG__
#ifdef _DEBUG_IDE__
kprintf("%s, read device %d block %d\n", __FUNCTION__, iDevice, iBlock);
#endif
#endif
// kprintf("%s, read device %d block %d\n", __FUNCTION__, iDevice, iBlock);
if ( !(pstBlock=pstId1GetBlock(iDevice, iBlock)) )
panic("\n%s:%s:%d line, GetBlock returned NULL\n", __FILE__,__FUNCTION__,__LINE__);
if ( pstBlock->ucUpToDate )
return pstBlock;
//POSITION();
// read from device...
IdeReadWriteBlock(IDE_READ_BLK, pstBlock);
#ifdef _DEBUG__
#ifdef _DEBUG_IDE__
POSITION();
#endif
#endif
Id1WaitOnBuffer(pstBlock);
//POSITION();
if ( pstBlock->ucUpToDate )
return pstBlock;
//POSITION();
Id1BufferRelease(pstBlock);
return NULL;
}
/************************************************************
*************************************************************
** Function Name: Id1BufferRelease
** Author: x.cheng
**
** Comment:
** release buffer...
**
** List of parameters:
** pucBlock - address
**
** Return value:
**
** Revisions:
**
*************************************************************
*************************************************************/
void Id1BufferRelease( ts_BufferBlock* pstBlock)
{
if (!pstBlock)
return;
Id1WaitOnBuffer(pstBlock);
if ( !(pstBlock->ucRefers--) )
panic("\n%s:%s:%d line, Trying to free free buffer\n", __FILE__,__FUNCTION__,__LINE__);
vMtsTaskWakeup(g_pstBufferWaitTask);
}
/************************************************************
*************************************************************
** Function Name: pstId1GetBlock
** Author: x.cheng
**
** Comment:
** Ok, this is GetBlock, and it isn't very clear, again to hinder
** race-conditions. Most of the code is seldom used, (ie repeating),
** so it should be much more efficient than it looks.
**
** List of parameters:
** iDevice - which device.
** iBlock - which block.
**
** Return value:
**
** Revisions:
**
*************************************************************
*************************************************************/
#define BADNESS(pstBlock) (((pstBlock)->ucDirty<<1)+(pstBlock)->ucLocked)
ts_BufferBlock* pstId1GetBlock(int iDevice, int iBlock)
{
ts_BufferBlock *pstTemp, *pstBlock;
//POSITION();
lbl_Repeat:
if ( (pstBlock=pstId1GetHashTable(iDevice, iBlock)) )
return pstBlock;
//POSITION();
pstTemp = g_pstFreeList;
do {
if (pstTemp->ucRefers)
continue;
if ( !pstBlock || BADNESS(pstTemp)<BADNESS(pstBlock) ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -