Exemple #1
0
// 클러스터 링크 테이블 내의 오프셋에 한 섹터를 씀 
// 내부적으로 사용하는 함수, 캐시 사용 
static BOOL kInternalWriteClusterLinkTableWithCache(DWORD dwOffset,BYTE* pbBuffer)
{
	CACHEBUFFER* pstCacheBuffer;

	// 캐시에 해당 클러스터 링크 테이블이 있는지 확인 
	pstCacheBuffer = kFindCacheBuffer(CACHE_CLUSTERLINKTABLEAREA,dwOffset);

	// 캐시 버퍼에 있다면 캐시에 씀 
	if(pstCacheBuffer!=NULL)
	{
		kMemCpy(pstCacheBuffer->pbBuffer,pbBuffer,512);

		// 쓰기룰 수행했으므로 버퍼의 내용을 수정된 것으로 표시 
		pstCacheBuffer->bChanged = TRUE;
		return TRUE;
	}

	// 캐시 버퍼에 없다면 캐시 버퍼를 할당받아서 캐시 내용을 갱신 
	pstCacheBuffer = kAllocateCacheBufferWithFlush(CACHE_CLUSTERLINKTABLEAREA);
	if(pstCacheBuffer==NULL)
	{
		return FALSE;
	}

	// 캐시 버퍼에 쓰고, 태그 정보를 갱신 
	kMemCpy(pstCacheBuffer->pbBuffer,pbBuffer,512);
	pstCacheBuffer->dwTag = dwOffset;

	// 쓰기를 수행했으므로 버퍼의 내용을 수정된 것으로 표시 
	pstCacheBuffer->bChanged = TRUE;

	return TRUE;
}
Exemple #2
0
// 데이터 영역의 오프셋에서 한 클러스터를 읽음 
// 내부적으로 사용하는 함수, 캐시 사용 
static BOOL kInternalReadClusterWithCache(DWORD dwOffset,BYTE* pbBuffer)
{
	CACHEBUFFER* pstCacheBuffer;

	// 캐시에 해당 데이터 클러스터가 있는지 확인 
	pstCacheBuffer = kFindCacheBuffer(CACHE_DATAAREA,dwOffset);

	// 캐시 버퍼에 있다면 캐시의 내용을 복사 
	if(pstCacheBuffer!=NULL)
	{
		kMemCpy(pbBuffer,pstCacheBuffer->pbBuffer,FILESYSTEM_CLUSTERSIZE);
		return TRUE;
	}

	// 캐시 버퍼에 없다면 하드 디스크에서 직접 읽음 
	if(kInternalReadClusterWithoutCache(dwOffset,pbBuffer)==FALSE)
	{
		return FALSE;
	}

	// 캐시 버퍼를 할당받아서 캐시 내용을 갱신 
	pstCacheBuffer = kAllocateCacheBufferWithFlush(CACHE_DATAAREA);
	if(pstCacheBuffer==NULL)
	{
		return FALSE;
	}

	// 케시 버퍼에 읽은 내용을 복사한 후 태그 정보를 갱신 
	kMemCpy(pstCacheBuffer->pbBuffer,pbBuffer,FILESYSTEM_CLUSTERSIZE);
	pstCacheBuffer->dwTag = dwOffset;

	// 읽기를 수행했으므로 버퍼의 내용을 수정되지 않은 것으로 표시 
	pstCacheBuffer->bChanged = FALSE;
	return TRUE;
}
Exemple #3
0
// 데이터 영역의 오프셋에 한 클러스터를 씀 
// 내부적으로 사용하는 함수, 캐시 사용 
static BOOL kInternalWriteClusterWithCache(DWORD dwOffset,BYTE* pbBuffer)
{
	CACHEBUFFER* pstCacheBuffer;

	// 캐시 버퍼에 해당 데이터가 클러스터가 있는지 확인 
	pstCacheBuffer = kFindCacheBuffer(CACHE_DATAAREA,dwOffset);

	// 캐시 버퍼에 있다면 캐시에 씀 
	if(pstCacheBuffer!=NULL)
	{
		kMemCpy(pstCacheBuffer->pbBuffer,pbBuffer,FILESYSTEM_CLUSTERSIZE);

		// 쓰기를 수행햇으므로 버퍼의 내용을 수정된 것으로 표시 
		pstCacheBuffer->bChanged = TRUE;

		return TRUE;
	}

	// 캐시 버퍼에 없다면 캐시를 할당받아서 캐시 내용을 갱신 
	pstCacheBuffer = kAllocateCacheBufferWithFlush(CACHE_DATAAREA);
	if(pstCacheBuffer==NULL)
	{
		return FALSE;
	}

	// 캐시 버퍼에 쓰고, 태그 정보를 갱신 
	kMemCpy(pstCacheBuffer->pbBuffer,pbBuffer,FILESYSTEM_CLUSTERSIZE);
	pstCacheBuffer->dwTag = dwOffset;

	// 쓰기를 수행했으므로 버퍼의 내용을 수정된 것으로 표시 
	pstCacheBuffer->bChanged = TRUE;

	return TRUE;
}
Exemple #4
0
/**
 *  인터럽트가 발생했을 때, 다른 태스크를 찾아 전환
 *      반드시 인터럽트나 예외가 발생했을 때 호출해야 함
 */
BOOL kScheduleInInterrupt( void )
{
    TCB* pstRunningTask, * pstNextTask;
    char* pcContextAddress;
    BOOL bPreviousFlag;
    
    // 임계 영역 시작
    bPreviousFlag = kLockForSystemData();
    
    // 전환할 태스크가 없으면 종료
    pstNextTask = kGetNextTaskToRun();
    if( pstNextTask == NULL )
    {
        // 임계 영역 끝
        kUnlockForSystemData( bPreviousFlag );
        return FALSE;
    }
    
    //==========================================================================
    //  태스크 전환 처리   
    //      인터럽트 핸들러에서 저장한 콘텍스트를 다른 콘텍스트로 덮어쓰는 방법으로 처리
    //==========================================================================
    pcContextAddress = ( char* ) IST_STARTADDRESS + IST_SIZE - sizeof( CONTEXT );
    
    // 현재 수행중인 태스크의 정보를 수정한 뒤 콘텍스트 전환
    pstRunningTask = gs_stScheduler.pstRunningTask;
    gs_stScheduler.pstRunningTask = pstNextTask;

    // 유휴 태스크에서 전환되었다면 사용한 Tick Count를 증가시킴
    if( ( pstRunningTask->qwFlags & TASK_FLAGS_IDLE ) == TASK_FLAGS_IDLE )
    {
        gs_stScheduler.qwSpendProcessorTimeInIdleTask += TASK_PROCESSORTIME;
    }    
    
    // 태스크 종료 플래그가 설정된 경우, 콘텍스트를 저장하지 않고 대기 리스트에만 삽입
    if( pstRunningTask->qwFlags & TASK_FLAGS_ENDTASK )
    {    
        kAddListToTail( &( gs_stScheduler.stWaitList ), pstRunningTask );
    }
    // 태스크가 종료되지 않으면 IST에 있는 콘텍스트를 복사하고, 현재 태스크를 준비 리스트로
    // 옮김
    else
    {
        kMemCpy( &( pstRunningTask->stContext ), pcContextAddress, sizeof( CONTEXT ) );
        kAddTaskToReadyList( pstRunningTask );
    }
    // 임계 영역 끝
    kUnlockForSystemData( bPreviousFlag );

    // 전환해서 실행할 태스크를 Running Task로 설정하고 콘텍스트를 IST에 복사해서
    // 자동으로 태스크 전환이 일어나도록 함
    kMemCpy( pcContextAddress, &( pstNextTask->stContext ), sizeof( CONTEXT ) );
    
    // 프로세서 사용 시간을 업데이트
    gs_stScheduler.iProcessorTime = TASK_PROCESSORTIME;
    return TRUE;
}
Exemple #5
0
/**
 *  램 디스크의 정보를 반환
 */
BOOL kReadRDDInformation( BOOL bPrimary, BOOL bMaster, 
        HDDINFORMATION* pstHDDInformation )
{
    // 자료구조 초기화
    kMemSet( pstHDDInformation, 0, sizeof( HDDINFORMATION ) );
    
    // 총 섹터 수와 시리얼 번호, 그리고 모델 번호만 설정
    pstHDDInformation->dwTotalSectors = gs_stRDDManager.dwTotalSectorCount;
    kMemCpy( pstHDDInformation->vwSerialNumber, "0000-0000", 9 );
    kMemCpy( pstHDDInformation->vwModelNumber, "MINT RAM Disk v1.0", 18 ); 

    return TRUE;
}
Exemple #6
0
// 루트 디렉터리의 해당 인덱스에 디렉터리 엔트리를 설정 
static BOOL kSetDirectoryEntryData(int iIndex,DIRECTORYENTRY* pstEntry)
{
	DIRECTORYENTRY* pstRootEntry;

	// 파일 시스템을 인식하지 못했거나 인덱스가 올바르지 않으면 실패 
	if((gs_stFileSystemManager.bMounted==FALSE)||(iIndex<0)||(iIndex>=FILESYSTEM_MAXDIRECTORYENTRYCOUNT))
	{
		kPrintf("FileSystem not mounted (Index=%d)\n",iIndex);
		return FALSE;
	}

	// 루트 디렉터리를 읽음 
	if(kReadCluster(0,gs_vbTempBuffer)==FALSE)
	{
		kPrintf("kReadCluster error\n");
		return FALSE;
	}

	// 루트 디렉터리에 있는 해당 데이터를 갱신 
	pstRootEntry = (DIRECTORYENTRY*)gs_vbTempBuffer;
	kMemCpy(pstRootEntry+iIndex,pstEntry,sizeof(DIRECTORYENTRY));

	// 루트 디렉터리에 씀 
	if(kWriteCluster(0,gs_vbTempBuffer)==FALSE)
	{
		kPrintf("kWriteCluster error\n");
		return FALSE;
	}

	return TRUE;
}
Exemple #7
0
// 루트 디렉터리에서 파일 이름이 일치하는 엔트리를 찾아서 인덱스를 반환 
static int kFindDirectoryEntry(const char* pcFileName,DIRECTORYENTRY* pstEntry)
{
	DIRECTORYENTRY* pstRootEntry;
	int i;
	int iLength;

	// 파일 시스템을 인식하지 못했으면 실패 
	if(gs_stFileSystemManager.bMounted==FALSE)
	{
		return -1;
	}

	// 루트 디렉터리를 읽음 
	if(kReadCluster(0,gs_vbTempBuffer)==FALSE)
	{
		return -1;
	}

	iLength = kStrLen(pcFileName);
	// 루트 디렉터리 안에서 루프를 돌면서 파일 이름이 일치하는 엔트리를 반환 
	pstRootEntry = (DIRECTORYENTRY*)gs_vbTempBuffer;
	for(i=0;i<FILESYSTEM_MAXDIRECTORYENTRYCOUNT;i++)
	{
		if(kMemCmp(pstRootEntry[i].vcFileName,pcFileName,iLength)==0)
		{
			kMemCpy(pstEntry,pstRootEntry+i,sizeof(DIRECTORYENTRY));
			return i;
		}
	}

	return -1;
}
Exemple #8
0
/**
 *  \n, \t와 같은 문자가 포함된 문자열을 출력한 후, 화면상의 다음 출력할 위치를 
 *  반환
 */
int kConsolePrintString( const char* pcBuffer )
{
    CHARACTER* pstScreen = ( CHARACTER* ) CONSOLE_VIDEOMEMORYADDRESS;
    int i, j;
    int iLength;
    int iPrintOffset;
    
    // 문자열을 출력할 위치를 저장
    iPrintOffset = gs_stConsoleManager.iCurrentPrintOffset;

    // 문자열의 길이만큼 화면에 출력
    iLength = kStrLen( pcBuffer );    
    for( i = 0 ; i < iLength ; i++ )
    {
        // 개행 처리
        if( pcBuffer[ i ] == '\n' )
        {
            // 출력할 위치를 80의 배수 컬럼으로 옮김
            // 현재 라인의 남은 문자열의 수만큼 더해서 다음 라인으로 위치시킴
            iPrintOffset += ( CONSOLE_WIDTH - ( iPrintOffset % CONSOLE_WIDTH ) );
        }
        // 탭 처리
        else if( pcBuffer[ i ] == '\t' )
        {
            // 출력할 위치를 8의 배수 컬럼으로 옮김
            iPrintOffset += ( 8 - ( iPrintOffset % 8 ) );
        }
        // 일반 문자열 출력
        else
        {
            // 비디오 메모리에 문자와 속성을 설정하여 문자를 출력하고
            // 출력할 위치를 다음으로 이동
            pstScreen[ iPrintOffset ].bCharactor = pcBuffer[ i ];
            pstScreen[ iPrintOffset ].bAttribute = CONSOLE_DEFAULTTEXTCOLOR;
            iPrintOffset++;
        }
        
        // 출력할 위치가 화면의 최댓값(80 * 25)을 벗어났으면 스크롤 처리
        if( iPrintOffset >= ( CONSOLE_HEIGHT * CONSOLE_WIDTH ) )
        {
            // 가장 윗줄을 제외한 나머지를 한줄 위로 복사
            kMemCpy( CONSOLE_VIDEOMEMORYADDRESS, 
                     CONSOLE_VIDEOMEMORYADDRESS + CONSOLE_WIDTH * sizeof( CHARACTER ),
                     ( CONSOLE_HEIGHT - 1 ) * CONSOLE_WIDTH * sizeof( CHARACTER ) );

            // 가장 마지막 라인은 공백으로 채움
            for( j = ( CONSOLE_HEIGHT - 1 ) * ( CONSOLE_WIDTH ) ; 
                 j < ( CONSOLE_HEIGHT * CONSOLE_WIDTH ) ; j++ )
            {
                // 공백 출력
                pstScreen[ j ].bCharactor = ' ';
                pstScreen[ j ].bAttribute = CONSOLE_DEFAULTTEXTCOLOR;
            }
            
            // 출력할 위치를 가장 아래쪽 라인의 처음으로 설정
            iPrintOffset = ( CONSOLE_HEIGHT - 1 ) * CONSOLE_WIDTH;
        }
    }
    return iPrintOffset;
}
Exemple #9
0
// Return parameter and its length
int kGetNextParameter( PARAMETERLIST * pstList, char * pcParameter )
{
	int i;
	int iLength;
	
	// If there is no parameter, exit
	if( pstList->iLength <= pstList->iCurrentPosition )
	{
		return 0;
	}
	
	// Search white space
	for ( i = pstList->iCurrentPosition ; i < pstList->iLength ; i++ )
	{
		if ( pstList->pcBuffer[i] == ' ' )
		{
			break;
		}
	}
	
	// Copy parameter and return length
	kMemCpy( pcParameter, pstList->pcBuffer + pstList->iCurrentPosition, i );
	iLength = i - pstList->iCurrentPosition;
	pcParameter[iLength] = '\0';
	
	// Update parameter position 
	pstList->iCurrentPosition += iLength + 1;
	return iLength;
}
Exemple #10
0
// 파일을 생성 
static BOOL kCreateFile(const char* pcFileName,DIRECTORYENTRY* pstEntry,int* piDirectoryEntryIndex)
{
	DWORD dwCluster;

	// 빈 클러스터를 찾아서 할당된 것으로 설정 
	dwCluster = kFindFreeCluster();
	if((dwCluster==FILESYSTEM_LASTCLUSTER)||(kSetClusterLinkData(dwCluster,FILESYSTEM_LASTCLUSTER)==FALSE))
	{
		return FALSE;
	}

	// 빈 디렉터리 엔트리를 검색 
	*piDirectoryEntryIndex = kFindFreeDirectoryEntry();
	if(*piDirectoryEntryIndex==-1)
	{
		// 실패하면 할당받은 클러스터를 반환해야 함 
		kSetClusterLinkData(dwCluster,FILESYSTEM_FREECLUSTER);
		return FALSE;
	}

	// 디렉터리 엔트리를 설정 
	kMemCpy(pstEntry->vcFileName,pcFileName,kStrLen(pcFileName)+1);
	pstEntry->dwStartClusterIndex = dwCluster;
	pstEntry->dwFileSize = 0;

	// 디렉터리 엔트리를 등록 
	if(kSetDirectoryEntryData(*piDirectoryEntryIndex,pstEntry)==FALSE)
	{
		// 실패하여 할당받은 클러스털르 반환해야 함 
		kSetClusterLinkData(dwCluster,FILESYSTEM_FREECLUSTER);
		return FALSE;
	}

	return TRUE;
}
Exemple #11
0
/**
 *  공백으로 구분된 파라미터의 내용과 길이를 반환
 */
int kGetNextParameter( PARAMETERLIST* pstList, char* pcParameter )
{
    int i;
    int iLength;

    // 더 이상 파라미터가 없으면 나감
    if( pstList->iLength <= pstList->iCurrentPosition )
    {
        return 0;
    }
    
    // 버퍼의 길이만큼 이동하면서 공백을 검색
    for( i = pstList->iCurrentPosition ; i < pstList->iLength ; i++ )
    {
        if( pstList->pcBuffer[ i ] == ' ' )
        {
            break;
        }
    }
    
    // 파라미터를 복사하고 길이를 반환
    kMemCpy( pcParameter, pstList->pcBuffer + pstList->iCurrentPosition, i );
    iLength = i - pstList->iCurrentPosition;
    pcParameter[ iLength ] = '\0';

    // 파라미터의 위치 업데이트
    pstList->iCurrentPosition += iLength + 1;
    return iLength;
}
Exemple #12
0
/**
 *  램 디스크에 여러 섹터를 씀
 */
int kWriteRDDSector( BOOL bPrimary, BOOL bMaster, DWORD dwLBA, int iSectorCount, 
        char* pcBuffer )
{
    int iRealWriteCount;
    
    // LBA 어드레스부터 끝까지 쓸 수 있는 섹터 수와 써야 할 섹터 수를 비교해서
    // 실제로 쓸 수 있는 수를 계산
    iRealWriteCount = MIN( gs_stRDDManager.dwTotalSectorCount - 
                      (dwLBA + iSectorCount), iSectorCount );

    // 데이터를 실제로 쓸 섹터 수만큼 램 디스크 메모리에 복사
    kMemCpy( gs_stRDDManager.pbBuffer + ( dwLBA * 512 ), pcBuffer, 
             iRealWriteCount * 512 );
    
    return iRealWriteCount;    
}
Exemple #13
0
/**
 *  램 디스크에서 여러 섹터를 읽어서 반환
 */
int kReadRDDSector( BOOL bPrimary, BOOL bMaster, DWORD dwLBA, int iSectorCount, 
        char* pcBuffer )
{
    int iRealReadCount;
    
    // LBA 어드레스부터 끝까지 읽을 수 있는 섹터 수와 읽어야 할 섹터 수를 비교해서
    // 실제로 읽을 수 있는 수를 계산
    iRealReadCount = MIN( gs_stRDDManager.dwTotalSectorCount - 
                      (dwLBA + iSectorCount), iSectorCount );

    // 램 디스크 메모리에서 데이터를 실제로 읽을 섹터 수만큼 복사해서 반환
    kMemCpy( pcBuffer, gs_stRDDManager.pbBuffer + ( dwLBA * 512 ), 
             iRealReadCount * 512 );
    
    return iRealReadCount;
}
Exemple #14
0
/**
 *  루트 디렉터리의 해당 인덱스에 위치하는 디렉터리 엔트리를 반환
 */
BOOL kGetDirectoryEntryData( int iIndex, DIRECTORYENTRY* pstEntry )
{
    DIRECTORYENTRY* pstRootEntry;
    
    // 파일 시스템을 인식하지 못했거나 인덱스가 올바르지 않으면 실패
    if( ( gs_stFileSystemManager.bMounted == FALSE ) ||
        ( iIndex < 0 ) || ( iIndex >= FILESYSTEM_MAXDIRECTORYENTRYCOUNT ) )
    {
        return FALSE;
    }

    // 루트 디렉터리를 읽음
    if( kReadCluster( 0, gs_vbTempBuffer ) == FALSE )
    {
        return FALSE;
    }    
    
    // 루트 디렉터리에 있는 해당 데이터를 갱신
    pstRootEntry = ( DIRECTORYENTRY* ) gs_vbTempBuffer;
    kMemCpy( pstEntry, pstRootEntry + iIndex, sizeof( DIRECTORYENTRY ) );
    return TRUE;
}
Exemple #15
0
/**
 *  인터럽트가 발생했을 때, 다른 태스크를 찾아 전환
 *      반드시 인터럽트나 예외가 발생했을 때 호출해야 함
 */
BOOL kScheduleInInterrupt( void )
{
    TCB* pstRunningTask, * pstNextTask;
    char* pcContextAddress;
    BYTE bCurrentAPICID;
    QWORD qwISTStartAddress;
        
    // 현재 로컬 APIC ID 확인
    bCurrentAPICID = kGetAPICID();
    
    // 임계 영역 시작
    kLockForSpinLock( &( gs_vstScheduler[ bCurrentAPICID ].stSpinLock ) );
        
    // 전환할 태스크가 없으면 종료
    pstNextTask = kGetNextTaskToRun( bCurrentAPICID );
    if( pstNextTask == NULL )
    {
        // 임계 영역 끝
        kUnlockForSpinLock( &( gs_vstScheduler[ bCurrentAPICID ].stSpinLock ) );
        return FALSE;
    }
    
    //==========================================================================
    //  태스크 전환 처리   
    //      인터럽트 핸들러에서 저장한 콘텍스트를 다른 콘텍스트로 덮어쓰는 방법으로 처리
    //==========================================================================
    // IST의 끝부분부터 코어 0 -> 코어 15 순으로 64Kbyte씩 쓰고 있으므로, 로컬 APIC ID를
    // 이용해서 IST 어드레스를 계산
    qwISTStartAddress = IST_STARTADDRESS + IST_SIZE - 
                        ( IST_SIZE / MAXPROCESSORCOUNT * bCurrentAPICID );
    pcContextAddress = ( char* ) qwISTStartAddress - sizeof( CONTEXT );
    
    pstRunningTask = gs_vstScheduler[ bCurrentAPICID ].pstRunningTask;
    gs_vstScheduler[ bCurrentAPICID ].pstRunningTask = pstNextTask;

    // 유휴 태스크에서 전환되었다면 사용한 Tick Count를 증가시킴
    if( ( pstRunningTask->qwFlags & TASK_FLAGS_IDLE ) == TASK_FLAGS_IDLE )
    {
        gs_vstScheduler[ bCurrentAPICID ].qwSpendProcessorTimeInIdleTask += TASK_PROCESSORTIME;
    }
    
    // 태스크 종료 플래그가 설정된 경우, 콘텍스트를 저장하지 않고 대기 리스트에만 삽입
    if( pstRunningTask->qwFlags & TASK_FLAGS_ENDTASK )
    {    
        kAddListToTail( &( gs_vstScheduler[ bCurrentAPICID ].stWaitList ), 
                        pstRunningTask );
    }
    // 태스크가 종료되지 않으면 IST에 있는 콘텍스트를 복사하고, 현재 태스크를 준비 리스트로
    // 옮김
    else
    {
        kMemCpy( &( pstRunningTask->stContext ), pcContextAddress, sizeof( CONTEXT ) );
    }
    
    // 다음에 수행할 태스크가 FPU를 쓴 태스크가 아니라면 TS bit 설정
    if( gs_vstScheduler[ bCurrentAPICID ].qwLastFPUUsedTaskID != 
        pstNextTask->stLink.qwID )
    {
        kSetTS();
    }
    else
    {
        kClearTS();
    }
    
    // 임계 영역 끝
    kUnlockForSpinLock( &( gs_vstScheduler[ bCurrentAPICID ].stSpinLock ) );
    
    // 전환해서 실행할 태스크를 Running Task로 설정하고 콘텍스트를 IST에 복사해서
    // 자동으로 태스크 전환이 일어나도록 함
    kMemCpy( pcContextAddress, &( pstNextTask->stContext ), sizeof( CONTEXT ) );
    
    // 종료하는 태스크가 아니면 스케줄러에 태스크 추가
    if( ( pstRunningTask->qwFlags & TASK_FLAGS_ENDTASK ) != TASK_FLAGS_ENDTASK )
    {
        // 스케줄러에 태스크를 추가, 부하 분산을 고려함
        kAddTaskToSchedulerWithLoadBalancing( pstRunningTask );
    }    
    
    // 프로세서 사용 시간을 업데이트
    gs_vstScheduler[ bCurrentAPICID ].iProcessorTime = TASK_PROCESSORTIME;
    
    return TRUE;
}
Exemple #16
0
// 파일 시스템의 정보를 반환 
void kGetFileSystemInformation(FILESYSTEMMANAGER* pstManager)
{
	kMemCpy(pstManager,&gs_stFileSystemManager,sizeof(gs_stFileSystemManager));
}
Exemple #17
0
/**
 *  접근한 시간을 전체적으로 낮춤
 */
static void kCutDownAccessTime( int iCacheTableIndex )
{
    CACHEBUFFER stTemp;
    CACHEBUFFER* pstCacheBuffer;
    BOOL bSorted;
    int i, j;

    // 캐시 테이블의 최대 개수를 넘어서면 실패
    if( iCacheTableIndex > CACHE_MAXCACHETABLEINDEX )
    {
        return ;
    }

    // 접근 시간이 아직 최대치를 넘지 않았다면 접근 시간을 줄일 필요 없음
    if( gs_stCacheManager.vdwAccessTime[ iCacheTableIndex ] < 0xfffffffe )
    {
        return ;
    }

    // 캐시 버퍼를 접근 시간으로 오름차순으로 정렬함
    // 버블 정렬(Bouble Sort) 사용
    pstCacheBuffer = gs_stCacheManager.vvstCacheBuffer[ iCacheTableIndex ];
    for( j = 0 ; j < gs_stCacheManager.vdwMaxCount[ iCacheTableIndex ] - 1 ; j++ )
    {
        // 기본은 정렬된 것으로 저장
        bSorted = TRUE;
        for( i = 0 ; i < gs_stCacheManager.vdwMaxCount[ iCacheTableIndex ] - 1 - j ;
             i++ )
        {
            // 인접한 두 데이터를 비교하여 접근 시간이 큰 것을 우측(i+1)에 위치시킴
            if( pstCacheBuffer[ i ].dwAccessTime > 
                pstCacheBuffer[ i + 1 ].dwAccessTime )
            {
                // 두 데이터를 교환하므로 정렬되지 않은 것으로 표시
                bSorted = FALSE;

                // i번째 캐시와 i+1번째 캐시를 교환
                kMemCpy( &stTemp, &( pstCacheBuffer[ i ] ), 
                        sizeof( CACHEBUFFER ) );
                kMemCpy( &( pstCacheBuffer[ i ] ), &( pstCacheBuffer[ i + 1 ] ), 
                        sizeof( CACHEBUFFER ) );
                kMemCpy( &( pstCacheBuffer[ i + 1 ] ), &stTemp, 
                        sizeof( CACHEBUFFER ) );
            }
        }

        // 다 정렬되었으면 루프를 빠져 나감
        if( bSorted == TRUE )
        {
            break;
        }
    }

    // 오름차순으로 정렬했으므로, 인덱스가 증가할수록 접근 시간 큰(최신) 캐시 버퍼임
    // 접근 시간을 0부터 순차적으로 설정하여 데이터 갱신
    for( i = 0 ; i < gs_stCacheManager.vdwMaxCount[ iCacheTableIndex ] ; i++ )
    {
        pstCacheBuffer[ i ].dwAccessTime = i;
    }

    // 접근 시간을 파일 시스템 캐시 자료구조에 저장하여 다음부터는 변경된 값으로 
    // 접근 시간을 설정하도록 함
    gs_stCacheManager.vdwAccessTime[ iCacheTableIndex ] = i;
}
Exemple #18
0
/**
 *  화면 버퍼의 변경된 내용을 GUI 콘솔 셸 윈도우 화면에 업데이트
 */
static void kProcessConsoleBuffer( QWORD qwWindowID )
{
    int i;
    int j;
    CONSOLEMANAGER* pstManager;
    CHARACTER* pstScreenBuffer;
    CHARACTER* pstPreviousScreenBuffer;
    RECT stLineArea;
    BOOL bChanged;
    static QWORD s_qwLastTickCount = 0;
    BOOL bFullRedraw;
    
    // 콘솔을 관리하는 자료구조를 반환 받아 화면 버퍼의 어드레스를 저장하고 
    // 이전 화면 버퍼의 어드레스도 저장
    pstManager = kGetConsoleManager();
    pstScreenBuffer = pstManager->pstScreenBuffer;
    pstPreviousScreenBuffer = gs_vstPreviousScreenBuffer;
    
    // 화면을 전체를 업데이트 한 지 5초가 지났으면 무조건 화면 전체를 다시 그림
    if( kGetTickCount() - s_qwLastTickCount > 5000 )
    {
        s_qwLastTickCount = kGetTickCount();
        bFullRedraw = TRUE;
    }
    else
    {
        bFullRedraw = FALSE;
    }

    // 화면 버퍼의 높이만큼 반복
    for( j = 0 ; j < CONSOLE_HEIGHT ; j++ )
    {
        // 처음에는 변경되지 않은 것으로 플래그 설정
        bChanged = FALSE;
        
        // 현재 라인에 변화가 있는지 비교하여 변경 여부 플래그를 처리
        for( i = 0 ; i < CONSOLE_WIDTH ; i++ )
        {
            // 문자를 비교하여 다르거나 전체를 새로 그려야 하면 이전 화면 버퍼에
            // 업데이트하고 변경 여부 플래그를 설정
            if( ( pstScreenBuffer->bCharactor != pstPreviousScreenBuffer->bCharactor ) ||
                ( bFullRedraw == TRUE ) )
            {
                // 문자를 화면에 출력
                kDrawText( qwWindowID, i * FONT_ENGLISHWIDTH + 2, 
                           j * FONT_ENGLISHHEIGHT + WINDOW_TITLEBAR_HEIGHT, 
                           RGB( 0, 255, 0 ), RGB( 0, 0, 0 ), 
                           &( pstScreenBuffer->bCharactor ), 1);
                
                // 이전 화면 버퍼로 값을 옮겨 놓고 현재 라인에 이전과
                // 다른 데이터가 있음을 표시
                kMemCpy( pstPreviousScreenBuffer, pstScreenBuffer, sizeof( CHARACTER ) );
                bChanged = TRUE;
            }

            pstScreenBuffer++;
            pstPreviousScreenBuffer++;
        }
        
        // 현재 라인에서 변경된 데이터가 있다면 현재 라인만 화면에 업데이트
        if( bChanged == TRUE )
        {
            // 현재 라인의 영역을 계산
            kSetRectangleData( 2, j * FONT_ENGLISHHEIGHT + WINDOW_TITLEBAR_HEIGHT,
                5 + FONT_ENGLISHWIDTH * CONSOLE_WIDTH, ( j + 1 ) * FONT_ENGLISHHEIGHT + 
                WINDOW_TITLEBAR_HEIGHT - 1, &stLineArea );
            // 윈도우의 일부만 화면 업데이트
            kUpdateScreenByWindowArea( qwWindowID, &stLineArea );
        }
    }
}
/**
 *  MP 설정 테이블의 정보를 모두 화면에 출력
 */
void kPrintMPConfigurationTable( void )
{
    MPCONFIGRUATIONMANAGER* pstMPConfigurationManager;
    QWORD qwMPFloatingPointerAddress;
    MPFLOATINGPOINTER* pstMPFloatingPointer;
    MPCONFIGURATIONTABLEHEADER* pstMPTableHeader;
    PROCESSORENTRY* pstProcessorEntry;
    BUSENTRY* pstBusEntry;
    IOAPICENTRY* pstIOAPICEntry;
    IOINTERRUPTASSIGNMENTENTRY* pstIOAssignmentEntry;
    LOCALINTERRUPTASSIGNMENTENTRY* pstLocalAssignmentEntry;
    QWORD qwBaseEntryAddress;
    char vcStringBuffer[ 20 ];
    WORD i;
    BYTE bEntryType;
    // 화면에 출력할 문자열
    char* vpcInterruptType[ 4 ] = { "INT", "NMI", "SMI", "ExtINT" };
    char* vpcInterruptFlagsPO[ 4 ] = { "Conform", "Active High", 
            "Reserved", "Active Low" };
    char* vpcInterruptFlagsEL[ 4 ] = { "Conform", "Edge-Trigger", "Reserved", 
            "Level-Trigger"};

    //==========================================================================
    // MP 설정 테이블 처리 함수를 먼저 호출하여 시스템 처리에 필요한 정보를 저장
    //==========================================================================
    kPrintf( "================ MP Configuration Table Summary ================\n" );
    pstMPConfigurationManager = kGetMPConfigurationManager();
    if( ( pstMPConfigurationManager->qwBaseEntryStartAddress == 0 ) &&
        ( kAnalysisMPConfigurationTable() == FALSE ) )
    {
        kPrintf( "MP Configuration Table Analysis Fail\n" );
        return ;
    }
    kPrintf( "MP Configuration Table Analysis Success\n" );
    
    kPrintf( "MP Floating Pointer Address : 0x%Q\n", 
            pstMPConfigurationManager->pstMPFloatingPointer );
    kPrintf( "PIC Mode Support : %d\n", pstMPConfigurationManager->bUsePICMode );
    kPrintf( "MP Configuration Table Header Address : 0x%Q\n",
            pstMPConfigurationManager->pstMPConfigurationTableHeader );
    kPrintf( "Base MP Configuration Table Entry Start Address : 0x%Q\n",
            pstMPConfigurationManager->qwBaseEntryStartAddress );
    kPrintf( "Processor Count : %d\n", pstMPConfigurationManager->iProcessorCount );
    kPrintf( "ISA Bus ID : %d\n", pstMPConfigurationManager->bISABusID );

    kPrintf( "Press any key to continue... ('q' is exit) : " );
    if( kGetCh() == 'q' )
    {
        kPrintf( "\n" );
        return ;
    }
    kPrintf( "\n" );            
    
    //==========================================================================
    // MP 플로팅 포인터 정보를 출력
    //==========================================================================
    kPrintf( "=================== MP Floating Pointer ===================\n" );
    pstMPFloatingPointer = pstMPConfigurationManager->pstMPFloatingPointer;
    kMemCpy( vcStringBuffer, pstMPFloatingPointer->vcSignature, 4 );
    vcStringBuffer[ 4 ] = '\0';
    kPrintf( "Signature : %s\n", vcStringBuffer );
    kPrintf( "MP Configuration Table Address : 0x%Q\n", 
            pstMPFloatingPointer->dwMPConfigurationTableAddress );
    kPrintf( "Length : %d * 16 Byte\n", pstMPFloatingPointer->bLength );
    kPrintf( "Version : %d\n", pstMPFloatingPointer->bRevision );
    kPrintf( "CheckSum : 0x%X\n", pstMPFloatingPointer->bCheckSum );
    kPrintf( "Feature Byte 1 : 0x%X ", pstMPFloatingPointer->vbMPFeatureByte[ 0 ] );
    // MP 설정 테이블 사용 여부 출력
    if( pstMPFloatingPointer->vbMPFeatureByte[ 0 ] == 0 )
    {
        kPrintf( "(Use MP Configuration Table)\n" );
    }
    else
    {
        kPrintf( "(Use Default Configuration)\n" );
    }    
    // PIC 모드 지원 여부 출력
    kPrintf( "Feature Byte 2 : 0x%X ", pstMPFloatingPointer->vbMPFeatureByte[ 1 ] );
    if( pstMPFloatingPointer->vbMPFeatureByte[ 2 ] & 
            MP_FLOATINGPOINTER_FEATUREBYTE2_PICMODE )
    {
        kPrintf( "(PIC Mode Support)\n" );
    }
    else
    {
        kPrintf( "(Virtual Wire Mode Support)\n" );
    }
    
    //==========================================================================
    // MP 설정 테이블 헤더 정보를 출력
    //==========================================================================
    kPrintf( "\n=============== MP Configuration Table Header ===============\n" );
    pstMPTableHeader = pstMPConfigurationManager->pstMPConfigurationTableHeader;
    kMemCpy( vcStringBuffer, pstMPTableHeader->vcSignature, 4 );
    vcStringBuffer[ 4 ] = '\0';
    kPrintf( "Signature : %s\n", vcStringBuffer );
    kPrintf( "Length : %d Byte\n", pstMPTableHeader->wBaseTableLength );
    kPrintf( "Version : %d\n", pstMPTableHeader->bRevision );
    kPrintf( "CheckSum : 0x%X\n", pstMPTableHeader->bCheckSum );
    kMemCpy( vcStringBuffer, pstMPTableHeader->vcOEMIDString, 8 );
    vcStringBuffer[ 8 ] = '\0';
    kPrintf( "OEM ID String : %s\n", vcStringBuffer );
    kMemCpy( vcStringBuffer, pstMPTableHeader->vcProductIDString, 12 );
    vcStringBuffer[ 12 ] = '\0';
    kPrintf( "Product ID String : %s\n", vcStringBuffer );
    kPrintf( "OEM Table Pointer : 0x%X\n", 
             pstMPTableHeader->dwOEMTablePointerAddress );
    kPrintf( "OEM Table Size : %d Byte\n", pstMPTableHeader->wOEMTableSize );
    kPrintf( "Entry Count : %d\n", pstMPTableHeader->wEntryCount );
    kPrintf( "Memory Mapped I/O Address Of Local APIC : 0x%X\n",
            pstMPTableHeader->dwMemoryMapIOAddressOfLocalAPIC );
    kPrintf( "Extended Table Length : %d Byte\n", 
            pstMPTableHeader->wExtendedTableLength );
    kPrintf( "Extended Table Checksum : 0x%X\n", 
            pstMPTableHeader->bExtendedTableChecksum );
    
    kPrintf( "Press any key to continue... ('q' is exit) : " );
    if( kGetCh() == 'q' )
    {
        kPrintf( "\n" );
        return ;
    }
    kPrintf( "\n" );
    
    //==========================================================================
    // 기본 MP 설정 테이블 엔트리 정보를 출력
    //==========================================================================
    kPrintf( "\n============= Base MP Configuration Table Entry =============\n" );
    qwBaseEntryAddress = pstMPFloatingPointer->dwMPConfigurationTableAddress + 
        sizeof( MPCONFIGURATIONTABLEHEADER );
    for( i = 0 ; i < pstMPTableHeader->wEntryCount ; i++ )
    {
        bEntryType = *( BYTE* ) qwBaseEntryAddress;
        switch( bEntryType )
        {
            // 프로세스 엔트리 정보 출력
        case MP_ENTRYTYPE_PROCESSOR:
            pstProcessorEntry = ( PROCESSORENTRY* ) qwBaseEntryAddress;
            kPrintf( "Entry Type : Processor\n" );
            kPrintf( "Local APIC ID : %d\n", pstProcessorEntry->bLocalAPICID );
            kPrintf( "Local APIC Version : 0x%X\n", pstProcessorEntry->bLocalAPICVersion );
            kPrintf( "CPU Flags : 0x%X ", pstProcessorEntry->bCPUFlags );
            // Enable/Disable 출력
            if( pstProcessorEntry->bCPUFlags & MP_PROCESSOR_CPUFLAGS_ENABLE )
            {
                kPrintf( "(Enable, " );
            }
            else
            {
                kPrintf( "(Disable, " );
            }
            // BSP/AP 출력
            if( pstProcessorEntry->bCPUFlags & MP_PROCESSOR_CPUFLAGS_BSP )
            {
                kPrintf( "BSP)\n" );
            }
            else
            {
                kPrintf( "AP)\n" );
            }            
            kPrintf( "CPU Signature : 0x%X\n", pstProcessorEntry->vbCPUSignature );
            kPrintf( "Feature Flags : 0x%X\n\n", pstProcessorEntry->dwFeatureFlags );

            // 프로세스 엔트리의 크기만큼 어드레스를 증가시켜 다음 엔트리로 이동
            qwBaseEntryAddress += sizeof( PROCESSORENTRY );
            break;

            // 버스 엔트리 정보 출력
        case MP_ENTRYTYPE_BUS:
            pstBusEntry = ( BUSENTRY* ) qwBaseEntryAddress;
            kPrintf( "Entry Type : Bus\n" );
            kPrintf( "Bus ID : %d\n", pstBusEntry->bBusID );
            kMemCpy( vcStringBuffer, pstBusEntry->vcBusTypeString, 6 );
            vcStringBuffer[ 6 ] = '\0';
            kPrintf( "Bus Type String : %s\n\n", vcStringBuffer );
            
            // 버스 엔트리의 크기만큼 어드레스를 증가시켜 다음 엔트리로 이동
            qwBaseEntryAddress += sizeof( BUSENTRY );
            break;
            
            // I/O APIC 엔트리
        case MP_ENTRYTYPE_IOAPIC:
            pstIOAPICEntry = ( IOAPICENTRY* ) qwBaseEntryAddress;
            kPrintf( "Entry Type : I/O APIC\n" );
            kPrintf( "I/O APIC ID : %d\n", pstIOAPICEntry->bIOAPICID );
            kPrintf( "I/O APIC Version : 0x%X\n", pstIOAPICEntry->bIOAPICVersion );
            kPrintf( "I/O APIC Flags : 0x%X ", pstIOAPICEntry->bIOAPICFlags );
            // Enable/Disable 출력
            if( pstIOAPICEntry->bIOAPICFlags == 1 )
            {
                kPrintf( "(Enable)\n" );
            }
            else
            {
                kPrintf( "(Disable)\n" );
            }
            kPrintf( "Memory Mapped I/O Address : 0x%X\n\n", 
                    pstIOAPICEntry->dwMemoryMapAddress );

            // I/O APIC 엔트리의 크기만큼 어드레스를 증가시켜 다음 엔트리로 이동
            qwBaseEntryAddress += sizeof( IOAPICENTRY );
            break;
            
            // I/O 인터럽트 지정 엔트리
        case MP_ENTRYTYPE_IOINTERRUPTASSIGNMENT:
            pstIOAssignmentEntry = ( IOINTERRUPTASSIGNMENTENTRY* ) 
                qwBaseEntryAddress;
            kPrintf( "Entry Type : I/O Interrupt Assignment\n" );
            kPrintf( "Interrupt Type : 0x%X ", pstIOAssignmentEntry->bInterruptType );
            // 인터럽트 타입 출력
            kPrintf( "(%s)\n", vpcInterruptType[ pstIOAssignmentEntry->bInterruptType ] );
            kPrintf( "I/O Interrupt Flags : 0x%X ", pstIOAssignmentEntry->wInterruptFlags );
            // 극성과 트리거 모드 출력
            kPrintf( "(%s, %s)\n", vpcInterruptFlagsPO[ pstIOAssignmentEntry->wInterruptFlags & 0x03 ], 
                    vpcInterruptFlagsEL[ ( pstIOAssignmentEntry->wInterruptFlags >> 2 ) & 0x03 ] );
            kPrintf( "Source BUS ID : %d\n", pstIOAssignmentEntry->bSourceBUSID );
            kPrintf( "Source BUS IRQ : %d\n", pstIOAssignmentEntry->bSourceBUSIRQ );
            kPrintf( "Destination I/O APIC ID : %d\n", 
                     pstIOAssignmentEntry->bDestinationIOAPICID );
            kPrintf( "Destination I/O APIC INTIN : %d\n\n", 
                     pstIOAssignmentEntry->bDestinationIOAPICINTIN );

            // I/O 인터럽트 지정 엔트리의 크기만큼 어드레스를 증가시켜 다음 엔트리로 이동
            qwBaseEntryAddress += sizeof( IOINTERRUPTASSIGNMENTENTRY );
            break;
            
            // 로컬 인터럽트 지정 엔트리
        case MP_ENTRYTYPE_LOCALINTERRUPTASSIGNMENT:
            pstLocalAssignmentEntry = ( LOCALINTERRUPTASSIGNMENTENTRY* )
                qwBaseEntryAddress;
            kPrintf( "Entry Type : Local Interrupt Assignment\n" );
            kPrintf( "Interrupt Type : 0x%X ", pstLocalAssignmentEntry->bInterruptType );
            // 인터럽트 타입 출력
            kPrintf( "(%s)\n", vpcInterruptType[ pstLocalAssignmentEntry->bInterruptType ] );
            kPrintf( "I/O Interrupt Flags : 0x%X ", pstLocalAssignmentEntry->wInterruptFlags );
            // 극성과 트리거 모드 출력
            kPrintf( "(%s, %s)\n", vpcInterruptFlagsPO[ pstLocalAssignmentEntry->wInterruptFlags & 0x03 ], 
                    vpcInterruptFlagsEL[ ( pstLocalAssignmentEntry->wInterruptFlags >> 2 ) & 0x03 ] );
            kPrintf( "Source BUS ID : %d\n", pstLocalAssignmentEntry->bSourceBUSID );
            kPrintf( "Source BUS IRQ : %d\n", pstLocalAssignmentEntry->bSourceBUSIRQ );
            kPrintf( "Destination Local APIC ID : %d\n", 
                     pstLocalAssignmentEntry->bDestinationLocalAPICID );
            kPrintf( "Destination Local APIC LINTIN : %d\n\n", 
                     pstLocalAssignmentEntry->bDestinationLocalAPICLINTIN );
            
            // 로컬 인터럽트 지정 엔트리의 크기만큼 어드레스를 증가시켜 다음 엔트리로 이동
            qwBaseEntryAddress += sizeof( LOCALINTERRUPTASSIGNMENTENTRY );
            break;
            
        default :
            kPrintf( "Unknown Entry Type. %d\n", bEntryType );
            break;
        }

        // 3개를 출력하고 나면 키 입력을 대기
        if( ( i != 0 ) && ( ( ( i + 1 ) % 3 ) == 0 ) )
        {
            kPrintf( "Press any key to continue... ('q' is exit) : " );
            if( kGetCh() == 'q' )
            {
                kPrintf( "\n" );
                return ;
            }
            kPrintf( "\n" );            
        }        
    }
}
/**
 *  이벤트 큐에 수신된 이벤트 처리
 */
BOOL kProcessEventQueueData( void )
{
    EVENT vstEvent[ WINDOWMANAGER_DATAACCUMULATECOUNT ];
    int iEventCount;
    WINDOWEVENT* pstWindowEvent;
    WINDOWEVENT* pstNextWindowEvent;
    QWORD qwWindowID;
    RECT stArea;
    RECT stOverlappedArea;
    int i;
    int j;
    
    //--------------------------------------------------------------------------
    // 윈도우 매니저 태스크의 이벤트 큐에 수신된 이벤트를 통합하는 부분
    //--------------------------------------------------------------------------
    for( i = 0 ; i < WINDOWMANAGER_DATAACCUMULATECOUNT ; i++ )
    {
        // 이벤트가 수신되기를 기다림
        if( kReceiveEventFromWindowManagerQueue( &( vstEvent[ i ] ) ) == FALSE )
        {
            // 처음부터 이벤트가 수신되지 않았으면 종료
            if( i == 0 )
            {
                return FALSE;
            }
            else
            {
                break;
            }
        }
        
        pstWindowEvent = &( vstEvent[ i ].stWindowEvent );
        // 윈도우 ID로 업데이트하는 이벤트가 수신되면 윈도우 영역을 이벤트 데이터에 삽입
        if( vstEvent[ i ].qwType == EVENT_WINDOWMANAGER_UPDATESCREENBYID )
        {
            // 윈도우의 크기를 이벤트 자료구조에 삽입
            if( kGetWindowArea( pstWindowEvent->qwWindowID, &stArea ) == FALSE )
            {
                kSetRectangleData( 0, 0, 0, 0, &( pstWindowEvent->stArea ) );
            }
            else
            {
                kSetRectangleData( 0, 0, kGetRectangleWidth( &stArea ) - 1, 
                    kGetRectangleHeight( &stArea ) - 1, &( pstWindowEvent->stArea ) );
            }
        }
    }
    
    // 저장된 이벤트를 검사하면서 합칠 수 있는 이벤트는 하나로 만듦
    iEventCount = i;
    
    for( j = 0 ; j < iEventCount ; j++ )
    {
        // 수신된 이벤트 중에 이벤트 중에서 이번에 처리할 것과 같은 윈도우에서
        // 발생하는 윈도우 이벤트를 검색
        pstWindowEvent = &( vstEvent[ j ].stWindowEvent );
        if( ( vstEvent[ j ].qwType != EVENT_WINDOWMANAGER_UPDATESCREENBYID ) &&
            ( vstEvent[ j ].qwType != EVENT_WINDOWMANAGER_UPDATESCREENBYWINDOWAREA ) &&
            ( vstEvent[ j ].qwType != EVENT_WINDOWMANAGER_UPDATESCREENBYSCREENAREA ) )
        {
            continue;
        }
        
        // 수신한 이벤트의 끝까지 루프를 수행하면서 수신된 이벤트를 검사
        for( i = j + 1 ; i < iEventCount ; i++ )
        {
            pstNextWindowEvent = &( vstEvent[ i ].stWindowEvent );
            // 화면 업데이트가 아니거나 윈도우 ID가 일치하지 않으면 제외
            if( ( ( vstEvent[ i ].qwType != EVENT_WINDOWMANAGER_UPDATESCREENBYID ) &&
                  ( vstEvent[ i ].qwType != EVENT_WINDOWMANAGER_UPDATESCREENBYWINDOWAREA ) &&
                  ( vstEvent[ i ].qwType != EVENT_WINDOWMANAGER_UPDATESCREENBYSCREENAREA ) ) ||
                ( pstWindowEvent->qwWindowID != pstNextWindowEvent->qwWindowID ) )
            {
                continue;
            }
        
            // 겹치는 영역을 계산하여 겹치지 않으면 제외
            if( kGetOverlappedRectangle( &( pstWindowEvent->stArea ), 
                &( pstNextWindowEvent->stArea ), &stOverlappedArea ) == FALSE )
            {
                continue;
            }
            
            // 두 영역이 일치하거나 어느 한쪽이 포함되면 이벤트를 통합
            if( kMemCmp( &( pstWindowEvent->stArea ), &stOverlappedArea,
                    sizeof( RECT ) ) == 0 )
            {
                // 현재 이벤트의 윈도우의 영역이 겹치는 영역과 일치한다면 
                // 다음 이벤트의 윈도우 영역이 현재 윈도우 영역과 같거나 포함함
                // 따라서 현재 이벤트에 다음 이벤트의 윈도우 영역을 복사하고
                // 다음 이벤트는 삭제
                kMemCpy( &( pstWindowEvent->stArea ), &( pstNextWindowEvent->stArea ), 
                         sizeof( RECT ) );
                vstEvent[ i ].qwType = EVENT_UNKNOWN;
            }
            else if( kMemCmp( &( pstNextWindowEvent->stArea ), &stOverlappedArea,
                     sizeof( RECT ) ) == 0 )
            {
                // 다음 이벤트의 윈도우의 영역이 겹치는 영역과 일치한다면 
                // 현재 이벤트의 윈도우 영역이 다음 윈도우 영역과 같거나 포함함
                // 따라서 윈도우 영역을 복사하지 않고 다음 이벤트를 삭제
                vstEvent[ i ].qwType = EVENT_UNKNOWN;
            }
        }
    }
    
    // 통합된 이벤트를 모두 처리
    for( i = 0 ; i < iEventCount ; i++ )
    {
        pstWindowEvent = &( vstEvent[ i ].stWindowEvent );
        
        // 타입 별로 처리
        switch( vstEvent[ i ].qwType )
        {
            // 현재 윈도우가 있는 영역을 화면에 업데이트
        case EVENT_WINDOWMANAGER_UPDATESCREENBYID:
            // 윈도우의 내부 영역을 화면에 업데이트
        case EVENT_WINDOWMANAGER_UPDATESCREENBYWINDOWAREA:
            // 윈도우를 기준으로 한 좌표를 화면 좌표로 변환하여 업데이트 처리
            if( kConvertRectClientToScreen( pstWindowEvent->qwWindowID, 
                    &( pstWindowEvent->stArea ), &stArea ) == TRUE )
            {
                // 윈도우 영역은 위에서 했으므로 그대로 화면 업데이트 함수를 호출
                kRedrawWindowByArea( &stArea, pstWindowEvent->qwWindowID );        
            }
            break;
    
            // 화면 좌표로 전달된 영역을 화면에 업데이트
        case EVENT_WINDOWMANAGER_UPDATESCREENBYSCREENAREA:
            kRedrawWindowByArea( &( pstWindowEvent->stArea ), WINDOW_INVALIDID );
            break;
    
        default:
            break;
        }
    }

    return TRUE;
}
Exemple #21
0
// 파일을 읽어 버퍼로 복사 
DWORD kReadFile(void* pvBuffer,DWORD dwSize,DWORD dwCount,FILE* pstFile)
{
	DWORD dwTotalCount;
	DWORD dwReadCount;
	DWORD dwOffsetInCluster;
	DWORD dwCopySize;
	FILEHANDLE* pstFileHandle;
	DWORD dwNextClusterIndex;

	// 핸들이 파일 타입이 아니면 실패 
	if((pstFile==NULL)||(pstFile->bType!=FILESYSTEM_TYPE_FILE))
	{
		return 0;
	}

	pstFileHandle = &(pstFile->stFileHandle);

	// 파일의 끝이거나 마지막 클러스터면 종료 
	if((pstFileHandle->dwCurrentOffset==pstFileHandle->dwFileSize)||(pstFileHandle->dwCurrentClusterIndex==FILESYSTEM_LASTCLUSTER))
	{
		return 0;
	}

	// 파일 끝과 비교해서 실제로 읽을 수 있는 값을 계산 
	dwTotalCount = MIN(dwSize*dwCount,pstFileHandle->dwFileSize-pstFileHandle->dwCurrentOffset);

	// 동기화 
	kLock(&(gs_stFileSystemManager.stMutex));

	// 계산된 값만큼 다 읽을 때까지 반복 
	dwReadCount=0;
	while(dwReadCount!=dwTotalCount)
	{
		//=====================================================================================
		// 클러스터를 읽어서 버퍼에 복사 
		//=====================================================================================
		// 현재 클러스터를 읽음 
		if(kReadCluster(pstFileHandle->dwCurrentClusterIndex,gs_vbTempBuffer)==FALSE)
		{
			break;
		}

		// 클러스터 내에서 파일 포인터가 존재하는 오프셋을 계산 
		dwOffsetInCluster = pstFileHandle->dwCurrentOffset%FILESYSTEM_CLUSTERSIZE;

		// 여러 클러스터에 걸쳐져 있다면 현재 클러스터에서 남은 만큼 읽고 다음 클러스터로 이동 
		dwCopySize = MIN(FILESYSTEM_CLUSTERSIZE-dwOffsetInCluster,dwTotalCount-dwReadCount);
		
		kMemCpy((char*)pvBuffer+dwReadCount,gs_vbTempBuffer+dwOffsetInCluster,dwCopySize);
		
		// 읽은 바이트 수와 파일 포인터의 위치를 갱신 
		dwReadCount +=dwCopySize;
		pstFileHandle->dwCurrentOffset +=dwCopySize;

		//=====================================================================================
		// 현재 클러스터를 끝까지 다 읽었으면 다음 클러스터로 이동 
		//=====================================================================================
		if((pstFileHandle->dwCurrentOffset%FILESYSTEM_CLUSTERSIZE)==0)
		{
			// 현재 클러스터의 링크 데이터를 찾아 다음 클러스터를 얻음 
			if(kGetClusterLinkData(pstFileHandle->dwCurrentClusterIndex,&dwNextClusterIndex)==FALSE)
			{
				break;
			}

			// 클러스터 정보를 갱신 
			pstFileHandle->dwPreviousClusterIndex=pstFileHandle->dwCurrentClusterIndex;
			pstFileHandle->dwCurrentClusterIndex=dwNextClusterIndex;
		}
	}

	// 동기화
	kUnlock(&(gs_stFileSystemManager.stMutex));

	// 읽은 바이트 수를 반환 
	return dwReadCount;
}
Exemple #22
0
// 버퍼의 데이터를 파일에 씀 
DWORD kWriteFile(const void* pvBuffer,DWORD dwSize,DWORD dwCount,FILE* pstFile)
{
	DWORD dwWriteCount;
	DWORD dwTotalCount;
	DWORD dwOffsetInCluster;
	DWORD dwCopySize;
	DWORD dwAllocatedClusterIndex;
	DWORD dwNextClusterIndex;
	DWORD dwUpperFileSize;
	FILEHANDLE* pstFileHandle;

	// 핸들이 파일 타입이 아니면 실패 
	if((pstFile==NULL)||(pstFile->bType!=FILESYSTEM_TYPE_FILE))
	{
		return 0;
	}

	pstFileHandle = &(pstFile->stFileHandle);

	// FileSize를 클러스터 크기 단위로 구한 수 
	dwUpperFileSize = ((pstFileHandle->dwFileSize+FILESYSTEM_CLUSTERSIZE)/FILESYSTEM_CLUSTERSIZE)*FILESYSTEM_CLUSTERSIZE;

	// 총 바이트 수 
	dwTotalCount = dwSize*dwCount;

	// 동기화 
	kLock(&(gs_stFileSystemManager.stMutex));

	// 다 쓸 때가지 반복 
	dwWriteCount=0;
	while(dwWriteCount!=dwTotalCount)
	{	
		
		// 클러스터 내에서 파일 포인터가 존재하는 오프셋을 계산 
		dwOffsetInCluster = pstFileHandle->dwCurrentOffset%FILESYSTEM_CLUSTERSIZE;
		dwCopySize = MIN(FILESYSTEM_CLUSTERSIZE-dwOffsetInCluster,dwTotalCount-dwWriteCount);
		
		
		dwAllocatedClusterIndex=-1;
		
		// 클러스터 시작 부분이면 kReadCluster가 필요없고, 시작 부분이 아니면 kReadCluster가 필요하다.
		if(dwUpperFileSize<=(pstFileHandle->dwCurrentOffset+dwCopySize))
		{
			// 빈 클러스터 검색 
			dwAllocatedClusterIndex = kFindFreeCluster();
			if(dwAllocatedClusterIndex==FILESYSTEM_LASTCLUSTER)
			{
				break;
			}

			// 검색된 클러스터를 마지막 클러스터로 설정 
			if(kSetClusterLinkData(dwAllocatedClusterIndex,FILESYSTEM_LASTCLUSTER)==FALSE)
			{
				break;
			}
		}

		
		if(pstFileHandle->dwCurrentOffset%FILESYSTEM_CLUSTERSIZE!=0)
		{
			if(pstFileHandle->dwCurrentClusterIndex==FILESYSTEM_LASTCLUSTER)
			{
				if(kReadCluster(pstFileHandle->dwPreviousClusterIndex,gs_vbTempBuffer)==FALSE)
				{
					break;

				}

			}
			else
			{
				if(kReadCluster(pstFileHandle->dwCurrentClusterIndex,gs_vbTempBuffer)==FALSE)
				{
					break;
				}

			}
		}


		// 여러 클러스터에 걸쳐 있다면 현재 클러스터에서 남은 만큼 쓰고 다음 클러스터로 이동 
		kMemCpy(gs_vbTempBuffer+dwOffsetInCluster,(char*)pvBuffer+dwWriteCount,dwCopySize);

		// 임시 버퍼에 삽입된 값을 디스크에 씀 
		if(pstFileHandle->dwCurrentClusterIndex==FILESYSTEM_LASTCLUSTER)
		{
			if(kWriteCluster(pstFileHandle->dwPreviousClusterIndex,gs_vbTempBuffer)==FALSE)
			{
				break;
			}
		}
		else 
		{
			if(kWriteCluster(pstFileHandle->dwCurrentClusterIndex,gs_vbTempBuffer)==FALSE)
			{
				break;
			}

		}

		// 쓴 바이트 수와 파일 포인터의 위치를 갱신 
		dwWriteCount+=dwCopySize;
		pstFileHandle->dwCurrentOffset+=dwCopySize;

		// 파일에 할당된 마지막 클러스터까지 Offset이 이동된 경우 이전에 할당된 클러스터와 연결시키기 
		if(dwOffsetInCluster+dwCopySize==FILESYSTEM_CLUSTERSIZE)
		{
			if(dwAllocatedClusterIndex!=-1)
			{
				if(kSetClusterLinkData(pstFileHandle->dwCurrentClusterIndex,dwAllocatedClusterIndex)==FALSE)
				{
					break;
				}

				pstFileHandle->dwPreviousClusterIndex = pstFileHandle->dwCurrentClusterIndex;
				pstFileHandle->dwCurrentClusterIndex = dwAllocatedClusterIndex;

			}
			else 
			{
				if(kGetClusterLinkData(pstFileHandle->dwCurrentClusterIndex,&dwNextClusterIndex)==FALSE)
				{
					break;
				}

				// 클러스터 정보를 갱신 
				pstFileHandle->dwPreviousClusterIndex = pstFileHandle->dwCurrentClusterIndex;
				pstFileHandle->dwCurrentClusterIndex = dwNextClusterIndex;

			}

			
		}

	}
	
	//=========================================================================================
	// 파일 크기가 변했다면 루트 디렉터리에 있는 디렉터리 엔트리 정보를 갱신 
	//=========================================================================================
	if(pstFileHandle->dwFileSize<pstFileHandle->dwCurrentOffset)
	{
		pstFileHandle->dwFileSize=pstFileHandle->dwCurrentOffset;
		kUpdateDirectoryEntry(pstFileHandle);
	}

	// 동기화 
	kUnlock(&(gs_stFileSystemManager.stMutex));
	return dwWriteCount;
}