Example #1
0
/**
 *  스캔 코드를 내부적으로 사용하는 키 데이터로 바꾼 후 키 큐에 삽입
 */
BOOL kConvertScanCodeAndPutQueue( BYTE bScanCode )
{
    KEYDATA stData;
    BOOL bResult = FALSE;
    BOOL bPreviousInterrupt;

    // 스캔 코드를 키 데이터에 삽입
    stData.bScanCode = bScanCode;
    
    // 스캔 코드를 ASCII 코드와 키 상태로 변환하여 키 데이터에 삽입
    if( kConvertScanCodeToASCIICode( bScanCode, &( stData.bASCIICode ), 
            &( stData.bFlags ) ) == TRUE )
    {
        // 인터럽트 불가
        bPreviousInterrupt = kSetInterruptFlag( FALSE );
        
        // 키 큐에 삽입
        bResult = kPutQueue( &gs_stKeyQueue, &stData );

        // 이전 인터럽트 플래그 복원
        kSetInterruptFlag( bPreviousInterrupt );
    }
    
    return bResult;
}
Example #2
0
/**
 *  키보드를 활성화 함
 */
BOOL kActivateKeyboard( void )
{
    int i, j;
    BOOL bPreviousInterrupt;
    BOOL bResult;
    
    // 인터럽트 불가
    bPreviousInterrupt = kSetInterruptFlag( FALSE );
    
    // 컨트롤 레지스터(포트 0x64)에 키보드 활성화 커맨드(0xAE)를 전달하여 키보드 디바이스 활성화
    kOutPortByte( 0x64, 0xAE );
        
    // 입력 버퍼(포트 0x60)가 빌 때까지 기다렸다가 키보드에 활성화 커맨드를 전송
    // 0xFFFF만큼 루프를 수행할 시간이면 충분히 커맨드가 전송될 수 있음
    // 0xFFFF 루프를 수행한 이후에도 입력 버퍼(포트 0x60)가 비지 않으면 무시하고 전송
    for( i = 0 ; i < 0xFFFF ; i++ )
    {
        // 입력 버퍼(포트 0x60)가 비어있으면 키보드 커맨드 전송 가능
        if( kIsInputBufferFull() == FALSE )
        {
            break;
        }
    }
    // 입력 버퍼(포트 0x60)로 키보드 활성화(0xF4) 커맨드를 전달하여 키보드로 전송
    kOutPortByte( 0x60, 0xF4 );
    
    // ACK가 올 때까지 대기함
    bResult = kWaitForACKAndPutOtherScanCode();
    
    // 이전 인터럽트 상태 복원
    kSetInterruptFlag( bPreviousInterrupt );
    return bResult;
}
Example #3
0
BOOL kActivateKeyboard(void)
{
	int i;
	int j;
	BOOL bPreviousInterrupt;
	BOOL bResult;

	// 인터럽트 막아놓고 원래의 상태를 저장
	bPreviousInterrupt = kSetInterruptFlag( FALSE );

	kOutPortByte(0x64, 0xAE); // 0x64(컨트롤(쓰기)레지스터에 0xAE 신호 발송 (키보드 디바이스 활성화) )

	for( i = 0 ; i < 0xFFFF ; i++ )
	{
		if (!kIsInputBufferFull()) // inputbuffer가 비었으면 키보드 활성화(디바이스X) 신호 보낼것
		{
			break;
		}
	}

	kOutPortByte(0x60, 0xF4); // 0x60에 0xF4 전송 (입력버퍼로 키보드 활성화 키 전송)

	// ACK가 올때까지 기다림
	bResult = kWaitForACKAndPutOtherScanCode();

	// 이전 인터럽트 상태 복원
	kSetInterruptFlag(bPreviousInterrupt);

	return bResult;

}
Example #4
0
// 태스크 사이에서 사용하는 데이터를 위한 잠근 해제 함수 
void kUnlock(MUTEX* pstMutex)
{
	BOOL bInterruptFlag;

	// 인터럽트를 비활성화 
	bInterruptFlag = kSetInterruptFlag(FALSE);

	// 뮤텍스를 잠근 태스크가 아니면 실패 
	if((pstMutex->bLockFlag==FALSE)||(pstMutex->qwTaskID!=kGetRunningTask(kGetAPICID())->stLink.qwID))
	{
		// 인터럽트를 복원 
		kSetInterruptFlag(bInterruptFlag);
		return ;
	}

	// 뮤텍스를 중복으로 잠갔으면 잠긴 횟수만 감소 
	if(pstMutex->dwLockCount>1)
	{
		pstMutex->dwLockCount--;
	}
	else 
	{
		// 해제된 것으로 설정, 잠긴 플래그는 가장 나중에 해제해야함 
		pstMutex->qwTaskID = TASK_INVALIDID;
		pstMutex->dwLockCount = 0;
		pstMutex->bLockFlag=FALSE;
	}

	// 인터럽트를 복원 
	kSetInterruptFlag(bInterruptFlag);
}
Example #5
0
// 시스템 전역에서 사용하는 데이터를 위한 잠금 해제 함수 
void kUnlockForSpinLock(SPINLOCK* pstSpinLock)
{
	BOOL bInterruptFlag;

	// 인터럽트를 먼저 비활성화 
	bInterruptFlag = kSetInterruptFlag(FALSE);

	// 스핀락을 잠근 태스크가 아니면 실패 
	if((pstSpinLock->bLockFlag==FALSE)||(pstSpinLock->bAPICID!=kGetAPICID()))
	{
		kSetInterruptFlag(bInterruptFlag);
		return;
	}

	// 스핀락을 중복으로 잠갔으면 잠김 횟수만 감소 
	if(pstSpinLock->dwLockCount>1)
	{
		pstSpinLock->dwLockCount--;
		return;
	}

	// 스핀락을 해제된 것으로 설정하고 인터럽트 플래그를 복원 
	// 인터럽트 플래그는 미리 저장해두었다가 사용 
	bInterruptFlag = pstSpinLock->bInterruptFlag;

	pstSpinLock->bAPICID = 0xFF;
	pstSpinLock->dwLockCount = 0;
	pstSpinLock->bInterruptFlag = FALSE;
	pstSpinLock->bLockFlag = FALSE;

	kSetInterruptFlag(bInterruptFlag);
}
Example #6
0
/**
 *  키보드 LED의 ON/OFF를 변경
 */
BOOL kChangeKeyboardLED( BOOL bCapsLockOn, BOOL bNumLockOn, BOOL bScrollLockOn )
{
    int i, j;
    BOOL bPreviousInterrupt;
    BOOL bResult;
    BYTE bData;
    
    // 인터럽트 불가
    bPreviousInterrupt = kSetInterruptFlag( FALSE );    
        
    // 키보드에 LED 변경 커맨드 전송하고 커맨드가 처리될 때까지 대기
    for( i = 0 ; i < 0xFFFF ; i++ )
    {
        // 출력 버퍼(포트 0x60)가 비었으면 커맨드 전송 가능
        if( kIsInputBufferFull() == FALSE )
        {
            break;
        }
    }
    
    // 출력 버퍼(포트 0x60)로 LED 상태 변경 커맨드(0xED) 전송
    kOutPortByte( 0x60, 0xED );
    for( i = 0 ; i < 0xFFFF ; i++ )
    {
        // 입력 버퍼(포트 0x60)가 비어있으면 키보드가 커맨드를 가져간 것임
        if( kIsInputBufferFull() == FALSE )
        {
            break;
        }
    }
    
    // ACK가 올때까지 대기함
    bResult = kWaitForACKAndPutOtherScanCode();

    if( bResult == FALSE )
    {
        // 이전 인터럽트 상태 복원
        kSetInterruptFlag( bPreviousInterrupt );
        return FALSE;
    }
    
    // LED 변경 값을 키보드로 전송하고 데이터가 처리가 완료될 때까지 대기
    kOutPortByte( 0x60, ( bCapsLockOn << 2 ) | ( bNumLockOn << 1 ) | bScrollLockOn );
    for( i = 0 ; i < 0xFFFF ; i++ )
    {
        // 입력 버퍼(포트 0x60)가 비어있으면 키보드가 LED 데이터를 가져간 것임
        if( kIsInputBufferFull() == FALSE )
        {
            break;
        }
    }
    
    // ACK가 올 때까지 대기함
    bResult = kWaitForACKAndPutOtherScanCode();

    // 이전 인터럽트 상태 복원
    kSetInterruptFlag( bPreviousInterrupt );
    return bResult;
}
Example #7
0
BOOL kChangeKeyboardLED( BOOL bCapsLockOn, BOOL bNumLockOn, BOOL bScrollLockOn )
{
	int i, j;
	BOOL bPreviousInterrupt;
	BOOL bResult;
	BYTE bData;

	// 인터럽트 불가
	bPreviousInterrupt = kSetInterruptFlag( FALSE );

	for( i = 0 ; i < 0xFFFF ; i++ )
	{
		if( kIsInputBufferFull() == FALSE ) // 입력버퍼가 빌때까지 기다림
		{
			break;
		}
	}

	// 출력 버퍼에 LED 상태 변경 한다는 커맨드 전송(0xED)
	kOutPortByte(0x60, 0xED);
	for( i = 0 ; i < 0xFFFF ; i++ )
	{
		if(kIsInputBufferFull() == FALSE) // 입력 버퍼가 빌때까지 기다림
			break;
	}

	// ACK를 기다림
	bResult = kWaitForACKAndPutOtherScanCode();

	if( bResult == FALSE )
	{
		kSetInterruptFlag( bPreviousInterrupt );
		return FALSE;
	}
	if ( j>= 100 ) // 일정 시간 이상 ACK가 안옴
		return FALSE;


	// 2비트 , 1비트, 0비트에 따라 온을 시켜줌
	kOutPortByte( 0x60, (bCapsLockOn << 2) | (bNumLockOn << 1) | bScrollLockOn );

	for( i = 0 ; i < 0xFFFF ; i++ )
	{
		if(kIsInputBufferFull() == FALSE)
		{
			break;
		}
	}

	bResult = kWaitForACKAndPutOtherScanCode();
	kSetInterruptFlag(bPreviousInterrupt);

	return bResult;
}
Example #8
0
// 시스템 전역에서 사용하는 데이터를 위한 잠금 함수 
void kLockForSpinLock(SPINLOCK* pstSpinLock)
{
	BOOL bInterruptFlag;

	// 인터럽트를 먼저 비활성화 
	bInterruptFlag = kSetInterruptFlag(FALSE);

	// 이미 잠겨 있다면 내가 잠갔는지 확인하고 그렇다면 잠금 횟수를 증가시킨 뒤 종료 
	if(kTestAndSet(&(pstSpinLock->bLockFlag),0,1)==FALSE)
	{
		// 자신이 잠갔다면 횟수만 증가시킴 
		if(pstSpinLock->bAPICID ==  kGetAPICID())
		{
			pstSpinLock->dwLockCount++;
			return;
		}

		// 자신이 아닌 경우는 잠긴 것이 해제될 때까지 대기 
		while(kTestAndSet(&(pstSpinLock->bLockFlag),0,1)==FALSE)
		{
			// kTestAndSet() 함수르 계속 호출하여 메모리 버스가 Lock 되는 것을 방지 
			 while(pstSpinLock->bLockFlag == TRUE)
			 {
				 kPause();
			 }
		}
	}

	// 잠김 설정, 잠김 플래그는 위의 kTestAndSet() 함수에서 처리 
	pstSpinLock->dwLockCount = 1;
	pstSpinLock->bAPICID = kGetAPICID();

	// 인터럽트 플래그를 저장하여 Unlock 수행 시 복원 
	pstSpinLock->bInterruptFlag = bInterruptFlag;
}
Example #9
0
/**
 *  키 큐에서 키 데이터를 제거
 */
BOOL kGetKeyFromKeyQueue( KEYDATA* pstData )
{
    BOOL bResult;
    BOOL bPreviousInterrupt;
    
    // 큐가 비었으면 키 데이터를 꺼낼 수 없음
    if( kIsQueueEmpty( &gs_stKeyQueue ) == TRUE )
    {
        return FALSE;
    }

    // 인터럽트 불가
    bPreviousInterrupt = kSetInterruptFlag( FALSE );

    // 키 큐에서 키 데이터를 제거
    bResult = kGetQueue( &gs_stKeyQueue, pstData );

    // 이전 인터럽트 플래그 복원
    kSetInterruptFlag( bPreviousInterrupt );
    return bResult;
}
Example #10
0
// 태스크 사이에서 사용하는 데이터를 위한 잠금 함수
void kLock(MUTEX* pstMutex)
{
	BYTE bCurrentAPICID;
	BOOL bInterruptFlag;

	// 인터럽트를 비활성화 
	bInterruptFlag = kSetInterruptFlag(FALSE);

	// 현재 코어의 로컬 APIC ID를 확인 
	bCurrentAPICID = kGetAPICID();

	// 이미 잠겨 있다면 내가 잠갔는지 확인하고 잠근 횟수를 증가시킨 뒤 종료 
	if(kTestAndSet(&(pstMutex->bLockFlag),0,1)==FALSE)
	{
		// 자신이 잠겼다면 횟수만 증가시킴 
		if(pstMutex->qwTaskID==kGetRunningTask(bCurrentAPICID)->stLink.qwID)
		{
			// 인터럽트를 복원 
			kSetInterruptFlag(bInterruptFlag);
			pstMutex->dwLockCount++;
			return;
		}

		// 자신이 아닌 경우는 잠긴 것이 해제될 때까지 대기 
		while(kTestAndSet(&(pstMutex->bLockFlag),0,1)==FALSE)
		{
			kSchedule();
		}
	}

	// 잠금 설정, 잠긴 플래그는 위의 kTestAndSet() 함수에서 처리함 	
	pstMutex->dwLockCount =1;
	pstMutex->qwTaskID=kGetRunningTask(bCurrentAPICID)->stLink.qwID;
	// 인터럽트를 복원 
	kSetInterruptFlag(bInterruptFlag);
}
Example #11
0
/**
 *  다른 태스크를 찾아서 전환
 *      인터럽트나 예외가 발생했을 때 호출하면 안됨
 *      단, 인터럽트나 예외에서 태스크를 종료하는 경우는 사용 가능
 */
BOOL kSchedule( void )
{
    TCB* pstRunningTask, * pstNextTask;
    BOOL bPreviousInterrupt;
    BYTE bCurrentAPICID;
    
    // 전환하는 도중 인터럽트가 발생하여 태스크 전환이 또 일어나면 곤란하므로 전환하는 
    // 동안 인터럽트가 발생하지 못하도록 설정
    bPreviousInterrupt = kSetInterruptFlag( FALSE );
    
    // 현재 로컬 APIC ID 확인
    bCurrentAPICID = kGetAPICID();
    
    // 전환할 태스크가 있어야 함
    if( kGetReadyTaskCount( bCurrentAPICID ) < 1 )
    {
        kSetInterruptFlag( bPreviousInterrupt );
        return FALSE;
    }
    
    // 임계 영역 시작
    kLockForSpinLock( &( gs_vstScheduler[ bCurrentAPICID ].stSpinLock ) );

    // 실행할 다음 태스크를 얻음
    pstNextTask = kGetNextTaskToRun( bCurrentAPICID );
    if( pstNextTask == NULL )
    {
        // 임계 영역 끝
        kUnlockForSpinLock( &( gs_vstScheduler[ bCurrentAPICID ].stSpinLock ) );
        kSetInterruptFlag( bPreviousInterrupt );
        return FALSE;
    }
    
    // 현재 수행중인 태스크의 정보를 수정한 뒤 콘텍스트 전환
    pstRunningTask = gs_vstScheduler[ bCurrentAPICID ].pstRunningTask; 
    gs_vstScheduler[ bCurrentAPICID ].pstRunningTask = pstNextTask;

    // 유휴 태스크에서 전환되었다면 사용한 프로세서 시간을 증가시킴
    if( ( pstRunningTask->qwFlags & TASK_FLAGS_IDLE ) == TASK_FLAGS_IDLE )
    {
        gs_vstScheduler[ bCurrentAPICID ].qwSpendProcessorTimeInIdleTask += 
            TASK_PROCESSORTIME - gs_vstScheduler[ bCurrentAPICID ].iProcessorTime;
    }

    // 다음에 수행할 태스크가 FPU를 쓴 태스크가 아니라면 TS 비트를 설정
    if( gs_vstScheduler[ bCurrentAPICID ].qwLastFPUUsedTaskID != 
        pstNextTask->stLink.qwID )
    {
        kSetTS();
    }
    else
    {
        kClearTS();
    }

    // 태스크 종료 플래그가 설정된 경우 콘텍스트를 저장할 필요가 없으므로, 대기 리스트에
    // 삽입하고 콘텍스트 전환
    if( pstRunningTask->qwFlags & TASK_FLAGS_ENDTASK )
    {
        kAddListToTail( &( gs_vstScheduler[ bCurrentAPICID ].stWaitList ), pstRunningTask );

        // 임계 영역 끝
        kUnlockForSpinLock( &( gs_vstScheduler[ bCurrentAPICID ].stSpinLock ) );

        // 태스크 전환
        kSwitchContext( NULL, &( pstNextTask->stContext ) );
    }
    else
    {
        kAddTaskToReadyList( bCurrentAPICID, pstRunningTask );
        
        // 임계 영역 끝
        kUnlockForSpinLock( &( gs_vstScheduler[ bCurrentAPICID ].stSpinLock ) );

        // 태스크 전환
        kSwitchContext( &( pstRunningTask->stContext ), &( pstNextTask->stContext ) );
    }

    // 프로세서 사용 시간을 업데이트
    gs_vstScheduler[ bCurrentAPICID ].iProcessorTime = TASK_PROCESSORTIME;
    
    // 인터럽트 플래그 복원
    kSetInterruptFlag( bPreviousInterrupt );
    return FALSE;
}
Example #12
0
/**
 *  시스템 전역에서 사용하는 데이터를 위한 잠금 해제 함수
 */
void kUnlockForSystemData( BOOL bInterruptFlag )
{
    kSetInterruptFlag( bInterruptFlag );
}
Example #13
0
/**
 *  시스템 전역에서 사용하는 데이터를 위한 잠금 함수
 */
BOOL kLockForSystemData( void )
{
    return kSetInterruptFlag( FALSE );
}
Example #14
0
/**
 *  멀티코어 프로세서 또는 멀티 프로세서 모드로 전환하는 함수
 */
BOOL kChangeToMultiCoreMode( void )
{
    MPCONFIGRUATIONMANAGER* pstMPManager;
    BOOL bInterruptFlag;
    int i;

    // Application Processor 활성화
    if( kStartUpApplicationProcessor() == FALSE )
    {
        return FALSE;
    }

    //--------------------------------------------------------------------------
    // 대칭 I/O 모드로 전환
    //--------------------------------------------------------------------------
    // MP 설정 매니저를 찾아서 PIC 모드인가 확인
    pstMPManager = kGetMPConfigurationManager();
    if( pstMPManager->bUsePICMode == TRUE )
    {
        // PIC 모드이면 I/O 포트 어드레스 0x22에 0x70을 먼저 전송하고 
        // I/O 포트 어드레스 0x23에 0x01을 전송하는 방법으로 IMCR 레지스터에 접근하여
        // PIC 모드 비활성화
        kOutPortByte( 0x22, 0x70 );
        kOutPortByte( 0x23, 0x01 );
    }

    // PIC 컨트롤러의 인터럽트를 모두 마스크하여 인터럽트가 발생할 수 없도록 함
    kMaskPICInterrupt( 0xFFFF );

    // 프로세서 전체의 로컬 APIC를 활성화
    kEnableGlobalLocalAPIC();
    
    // 현재 코어의 로컬 APIC를 활성화
    kEnableSoftwareLocalAPIC();

    // 인터럽트를 불가로 설정
    bInterruptFlag = kSetInterruptFlag( FALSE );
    
    // 모든 인터럽트를 수신할 수 있도록 태스크 우선 순위 레지스터를 0으로 설정
    kSetTaskPriority( 0 );

    // 로컬 APIC의 로컬 벡터 테이블을 초기화
    kInitializeLocalVectorTable();

    // 대칭 I/O 모드로 변경되었음을 설정
    kSetSymmetricIOMode( TRUE );
    
    // I/O APIC 초기화
    kInitializeIORedirectionTable();
        
    // 이전 인터럽트 플래그를 복원
    kSetInterruptFlag( bInterruptFlag );

    // 인터럽트 부하 분산 기능 활성화
    kSetInterruptLoadBalancing( TRUE );

    // 태스크 부하 분산 기능 활성화
    for( i = 0 ; i < MAXPROCESSORCOUNT ; i++ )
    {
        kSetTaskLoadBalancing( i, TRUE );
    }
    
    return TRUE;
}