/** * 타이머 인터럽트의 핸들러 */ void kTimerHandler( int iVectorNumber ) { char vcBuffer[] = "[INT: , ]"; static int g_iTimerInterruptCount = 0; //========================================================================= // 인터럽트가 발생했음을 알리려고 메시지를 출력하는 부분 // 인터럽트 벡터를 화면 오른쪽 위에 2자리 정수로 출력 vcBuffer[ 5 ] = '0' + iVectorNumber / 10; vcBuffer[ 6 ] = '0' + iVectorNumber % 10; // 발생한 횟수 출력 vcBuffer[ 8 ] = '0' + g_iTimerInterruptCount; g_iTimerInterruptCount = ( g_iTimerInterruptCount + 1 ) % 10; kPrintStringXY( 70, 0, vcBuffer ); //========================================================================= // EOI 전송 kSendEOIToPIC( iVectorNumber - PIC_IRQSTARTVECTOR ); // 타이머 발생 횟수를 증가 g_qwTickCount++; // 태스크가 사용한 프로세서의 시간을 줄임 kDecreaseProcessorTime(); // 프로세서가 사용할 수 있는 시간을 다 썼다면 태스크 전환 수행 if( kIsProcessorTimeExpired() == TRUE ) { kScheduleInInterrupt(); } }
/** * 키보드 인터럽트의 핸들러 */ void kKeyboardHandler( int iVectorNumber ) { char vcBuffer[] = "[INT: , ]"; static int g_iKeyboardInterruptCount = 0; BYTE bTemp; //========================================================================= // 인터럽트가 발생했음을 알리려고 메시지를 출력하는 부분 // 인터럽트 벡터를 화면 왼쪽 위에 2자리 정수로 출력 vcBuffer[ 5 ] = '0' + iVectorNumber / 10; vcBuffer[ 6 ] = '0' + iVectorNumber % 10; // 발생한 횟수 출력 vcBuffer[ 8 ] = '0' + g_iKeyboardInterruptCount; g_iKeyboardInterruptCount = ( g_iKeyboardInterruptCount + 1 ) % 10; kPrintStringXY( 0, 0, vcBuffer ); //========================================================================= // 키보드 컨트롤러에서 데이터를 읽어서 ASCII로 변환하여 큐에 삽입 if( kIsOutputBufferFull() == TRUE ) { bTemp = kGetKeyboardScanCode(); kConvertScanCodeAndPutQueue( bTemp ); } // EOI 전송 kSendEOIToPIC( iVectorNumber - PIC_IRQSTARTVECTOR ); }
/** * 공통으로 사용하는 예외 핸들러 */ void kCommonExceptionHandler( int iVectorNumber, QWORD qwErrorCode ) { char vcBuffer[ 3 ] = { 0, }; // 인터럽트 벡터를 화면 오른쪽 위에 2자리 정수로 출력 vcBuffer[ 0 ] = '0' + iVectorNumber / 10; vcBuffer[ 1 ] = '0' + iVectorNumber % 10; kPrintStringXY( 0, 0, "====================================================" ); kPrintStringXY( 0, 1, " Exception Occur~!!!! " ); kPrintStringXY( 0, 2, " Vector: " ); kPrintStringXY( 27, 2, vcBuffer ); kPrintStringXY( 0, 3, "====================================================" ); while( 1 ) ; }
/** * 하드 디스크에서 발생하는 인터럽트의 핸들러 */ void kHDDHandler( int iVectorNumber ) { char vcBuffer[] = "[INT: , ]"; static int g_iHDDInterruptCount = 0; BYTE bTemp; int iIRQ; //========================================================================= // 인터럽트가 발생했음을 알리려고 메시지를 출력하는 부분 // 인터럽트 벡터를 화면 왼쪽 위에 2자리 정수로 출력 vcBuffer[ 5 ] = '0' + iVectorNumber / 10; vcBuffer[ 6 ] = '0' + iVectorNumber % 10; // 발생한 횟수 출력 vcBuffer[ 8 ] = '0' + g_iHDDInterruptCount; g_iHDDInterruptCount = ( g_iHDDInterruptCount + 1 ) % 10; // 왼쪽 위에 있는 메시지와 겹치지 않도록 (10, 0)에 출력 kPrintStringXY( 10, 0, vcBuffer ); //========================================================================= // 첫 번째 PATA 포트의 인터럽트 발생 여부를 TRUE로 설정 kSetHDDInterruptFlag( TRUE, TRUE ); // 인터럽트 벡터에서 IRQ 번호 추출 iIRQ = iVectorNumber - PIC_IRQSTARTVECTOR; // EOI 전송 kSendEOI( iIRQ ); // 인터럽트 발생 횟수를 업데이트 kIncreaseInterruptCount( iIRQ ); // 부하 분산(Load Balancing) 처리 kProcessLoadBalancing( iIRQ ); }
/** * Device Not Available 예외의 핸들러 */ void kDeviceNotAvailableHandler( int iVectorNumber ) { TCB* pstFPUTask, * pstCurrentTask; QWORD qwLastFPUTaskID; BYTE bCurrentAPICID; //========================================================================= // FPU 예외가 발생했음을 알리려고 메시지를 출력하는 부분 char vcBuffer[] = "[EXC: , ]"; static int g_iFPUInterruptCount = 0; // 예외 벡터를 화면 오른쪽 위에 2자리 정수로 출력 vcBuffer[ 5 ] = '0' + iVectorNumber / 10; vcBuffer[ 6 ] = '0' + iVectorNumber % 10; // 발생한 횟수 출력 vcBuffer[ 8 ] = '0' + g_iFPUInterruptCount; g_iFPUInterruptCount = ( g_iFPUInterruptCount + 1 ) % 10; kPrintStringXY( 0, 0, vcBuffer ); //========================================================================= // 현재 코어의 로컬 APIC ID를 확인 bCurrentAPICID = kGetAPICID(); // CR0 컨트롤 레지스터의 TS 비트를 0으로 설정 kClearTS(); // 이전에 FPU를 사용한 태스크가 있는지 확인하여, 있다면 FPU의 상태를 태스크에 저장 qwLastFPUTaskID = kGetLastFPUUsedTaskID( bCurrentAPICID ); pstCurrentTask = kGetRunningTask( bCurrentAPICID ); // 이전에 FPU를 사용한 것이 자신이면 아무것도 안 함 if( qwLastFPUTaskID == pstCurrentTask->stLink.qwID ) { return ; } // FPU를 사용한 태스크가 있으면 FPU 상태를 저장 else if( qwLastFPUTaskID != TASK_INVALIDID ) { pstFPUTask = kGetTCBInTCBPool( GETTCBOFFSET( qwLastFPUTaskID ) ); if( ( pstFPUTask != NULL ) && ( pstFPUTask->stLink.qwID == qwLastFPUTaskID ) ) { kSaveFPUContext( pstFPUTask->vqwFPUContext ); } } // 현재 태스크가 FPU를 사용한 적이 있는 지 확인하여 FPU를 사용한 적이 없다면 // 초기화하고, 사용한적이 있다면 저장된 FPU 콘텍스트를 복원 if( pstCurrentTask->bFPUUsed == FALSE ) { kInitializeFPU(); pstCurrentTask->bFPUUsed = TRUE; } else { kLoadFPUContext( pstCurrentTask->vqwFPUContext ); } // FPU를 사용한 태스크 ID를 현재 태스크로 변경 kSetLastFPUUsedTaskID( bCurrentAPICID, pstCurrentTask->stLink.qwID ); }
/** * 공통으로 사용하는 인터럽트 핸들러 */ void kCommonInterruptHandler( int iVectorNumber ) { char vcBuffer[] = "[INT: , ]"; static int g_iCommonInterruptCount = 0; int iIRQ; //========================================================================= // 인터럽트가 발생했음을 알리려고 메시지를 출력하는 부분 // 인터럽트 벡터를 화면 오른쪽 위에 2자리 정수로 출력 vcBuffer[ 5 ] = '0' + iVectorNumber / 10; vcBuffer[ 6 ] = '0' + iVectorNumber % 10; // 발생한 횟수 출력 vcBuffer[ 8 ] = '0' + g_iCommonInterruptCount; g_iCommonInterruptCount = ( g_iCommonInterruptCount + 1 ) % 10; kPrintStringXY( 70, 0, vcBuffer ); //========================================================================= // 인터럽트 벡터에서 IRQ 번호 추출 iIRQ = iVectorNumber - PIC_IRQSTARTVECTOR; // EOI 전송 kSendEOI( iIRQ ); // 인터럽트 발생 횟수를 업데이트 kIncreaseInterruptCount( iIRQ ); // 부하 분산(Load Balancing) 처리 kProcessLoadBalancing( iIRQ ); }
/** * 하드 디스크에서 발생하는 인터럽트의 핸들러 */ void kHDDHandler( int iVectorNumber ) { char vcBuffer[] = "[INT: , ]"; static int g_iHDDInterruptCount = 0; BYTE bTemp; //========================================================================= // 인터럽트가 발생했음을 알리려고 메시지를 출력하는 부분 // 인터럽트 벡터를 화면 왼쪽 위에 2자리 정수로 출력 vcBuffer[ 5 ] = '0' + iVectorNumber / 10; vcBuffer[ 6 ] = '0' + iVectorNumber % 10; // 발생한 횟수 출력 vcBuffer[ 8 ] = '0' + g_iHDDInterruptCount; g_iHDDInterruptCount = ( g_iHDDInterruptCount + 1 ) % 10; // 왼쪽 위에 있는 메시지와 겹치지 않도록 (10, 0)에 출력 kPrintStringXY( 10, 0, vcBuffer ); //========================================================================= // 첫 번째 PATA 포트의 인터럽트 발생 여부를 TRUE로 설정 kSetHDDInterruptFlag( TRUE, TRUE ); // PIC 컨트롤러로 EOI 전송 kSendEOIToPIC( iVectorNumber - PIC_IRQSTARTVECTOR ); // 로컬 APIC로 EOI 전송 kSendEOIToLocalAPIC(); }
/** * 공통으로 사용하는 예외 핸들러 */ void kCommonExceptionHandler( int iVectorNumber, QWORD qwErrorCode ) { char vcBuffer[ 100 ]; BYTE bAPICID; TCB* pstTask; // 현재 예외가 발생한 코어를 반환 bAPICID = kGetAPICID(); // 현재 코어에서 실행 중인 태스크를 반환 pstTask = kGetRunningTask( bAPICID ); // 메시지 출력 kPrintStringXY( 0, 0, "====================================================" ); kPrintStringXY( 0, 1, " Exception Occur~!!!! " ); // 예외 벡터와 코어 ID, 에러코드를 출력 kSPrintf( vcBuffer, " Vector:%d Core ID:0x%X ErrorCode:0x%X ", iVectorNumber, bAPICID, qwErrorCode ); kPrintStringXY( 0, 2, vcBuffer ); // 태스크 ID를 출력 kSPrintf( vcBuffer, " Task ID:0x%Q", pstTask->stLink.qwID ); kPrintStringXY( 0, 3, vcBuffer ); kPrintStringXY( 0, 4, "====================================================" ); // 유저 레벨 태스크의 경우는 무한 루프를 수행하지 않고 태스크를 종료시키고 다른 // 태스크로 전환 if( pstTask->qwFlags & TASK_FLAGS_USERLEVEL ) { // 태스크 종료 kEndTask( pstTask->stLink.qwID ); // 무한 루프 수행 // kEndTask() 함수에서 다른 태스크로 전환하므로 실제로 여기는 수행되지 않음 while( 1 ) { ; } } // 커널 레벨인 경우는 무한 루프 수행 else { // 무한 루프 수행 while( 1 ) { ; } } }
/** * 마우스 인터럽트의 핸들러 */ void kMouseHandler( int iVectorNumber ) { char vcBuffer[] = "[INT: , ]"; static int g_iMouseInterruptCount = 0; BYTE bTemp; int iIRQ; //========================================================================= // 인터럽트가 발생했음을 알리려고 메시지를 출력하는 부분 // 인터럽트 벡터를 화면 왼쪽 위에 2자리 정수로 출력 vcBuffer[ 5 ] = '0' + iVectorNumber / 10; vcBuffer[ 6 ] = '0' + iVectorNumber % 10; // 발생한 횟수 출력 vcBuffer[ 8 ] = '0' + g_iMouseInterruptCount; g_iMouseInterruptCount = ( g_iMouseInterruptCount + 1 ) % 10; kPrintStringXY( 0, 0, vcBuffer ); //========================================================================= // 출력 버퍼(포트 0x60)에 수신된 데이터가 있는지 여부를 확인하여 읽은 데이터를 // 키 큐 또는 마우스 큐에 삽입 if( kIsOutputBufferFull() == TRUE ) { // 마우스 데이터가 아니면 키 큐에 삽입 if( kIsMouseDataInOutputBuffer() == FALSE ) { // 출력 버퍼(포트 0x60)에서 키 스캔 코드를 읽는 용도의 함수지만 키보드와 마우스 // 데이터는 출력 버퍼를 공통으로 사용하므로 마우스 데이터를 읽는데도 사용 가능 bTemp = kGetKeyboardScanCode(); // 키 큐에 삽입 kConvertScanCodeAndPutQueue( bTemp ); } // 마우스 데이터이면 마우스 큐에 삽입 else { // 출력 버퍼(포트 0x60)에서 키 스캔 코드를 읽는 용도의 함수지만 키보드와 마우스 // 데이터는 출력 버퍼를 공통으로 사용하므로 마우스 데이터를 읽는데도 사용 가능 bTemp = kGetKeyboardScanCode(); // 마우스 큐에 삽입 kAccumulateMouseDataAndPutQueue( bTemp ); } } // 인터럽트 벡터에서 IRQ 번호 추출 iIRQ = iVectorNumber - PIC_IRQSTARTVECTOR; // EOI 전송 kSendEOI( iIRQ ); // 인터럽트 발생 횟수를 업데이트 kIncreaseInterruptCount( iIRQ ); // 부하 분산(Load Balancing) 처리 kProcessLoadBalancing( iIRQ ); }
/** * 공통으로 사용하는 인터럽트 핸들러 */ void kCommonInterruptHandler( int iVectorNumber ) { char vcBuffer[] = "[INT: , ]"; static int g_iCommonInterruptCount = 0; //========================================================================= // 인터럽트가 발생했음을 알리려고 메시지를 출력하는 부분 // 인터럽트 벡터를 화면 오른쪽 위에 2자리 정수로 출력 vcBuffer[ 5 ] = '0' + iVectorNumber / 10; vcBuffer[ 6 ] = '0' + iVectorNumber % 10; // 발생한 횟수 출력 vcBuffer[ 8 ] = '0' + g_iCommonInterruptCount; g_iCommonInterruptCount = ( g_iCommonInterruptCount + 1 ) % 10; kPrintStringXY( 70, 0, vcBuffer ); //========================================================================= // EOI 전송 kSendEOIToPIC( iVectorNumber - PIC_IRQSTARTVECTOR ); }
/** * 타이머 인터럽트의 핸들러 */ void kTimerHandler( int iVectorNumber ) { char vcBuffer[] = "[INT: , ]"; static int g_iTimerInterruptCount = 0; int iIRQ; BYTE bCurrentAPICID; //========================================================================= // 인터럽트가 발생했음을 알리려고 메시지를 출력하는 부분 // 인터럽트 벡터를 화면 오른쪽 위에 2자리 정수로 출력 vcBuffer[ 5 ] = '0' + iVectorNumber / 10; vcBuffer[ 6 ] = '0' + iVectorNumber % 10; // 발생한 횟수 출력 vcBuffer[ 8 ] = '0' + g_iTimerInterruptCount; g_iTimerInterruptCount = ( g_iTimerInterruptCount + 1 ) % 10; kPrintStringXY( 70, 0, vcBuffer ); //========================================================================= // 인터럽트 벡터에서 IRQ 번호 추출 iIRQ = iVectorNumber - PIC_IRQSTARTVECTOR; // EOI 전송 kSendEOI( iIRQ ); // 인터럽트 발생 횟수를 업데이트 kIncreaseInterruptCount( iIRQ ); // IRQ 0 인터럽트 처리는 Bootstrap Processor만 처리 bCurrentAPICID = kGetAPICID(); if( bCurrentAPICID == 0 ) { // 타이머 발생 횟수를 증가 g_qwTickCount++; } // 태스크가 사용한 프로세서의 시간을 줄임 kDecreaseProcessorTime( bCurrentAPICID ); // 프로세서가 사용할 수 있는 시간을 다 썼다면 태스크 전환 수행 if( kIsProcessorTimeExpired( bCurrentAPICID ) == TRUE ) { kScheduleInInterrupt(); } }
/** * 셸의 메인 루프 */ void kStartConsoleShell( void ) { char vcCommandBuffer[ CONSOLESHELL_MAXCOMMANDBUFFERCOUNT ]; int iCommandBufferIndex = 0; BYTE bKey; int iCursorX, iCursorY; CONSOLEMANAGER* pstConsoleManager; // 콘솔을 관리하는 자료구조를 반환 pstConsoleManager = kGetConsoleManager(); // 프롬프트 출력 kPrintf( CONSOLESHELL_PROMPTMESSAGE ); // 콘솔 셸 종료 플래그가 TRUE가 될 때까지 반복 while( pstConsoleManager->bExit == FALSE ) { bKey = kGetCh(); // 콘솔 셸 종료 플래그가 설정된 경우 루프를 종료 if( pstConsoleManager->bExit == TRUE ) { break; } if( bKey == KEY_BACKSPACE ) { if( iCommandBufferIndex > 0 ) { // 현재 커서 위치를 얻어서 한 문자 앞으로 이동한 다음 공백을 출력하고 // 커맨드 버퍼에서 마지막 문자 삭제 kGetCursor( &iCursorX, &iCursorY ); kPrintStringXY( iCursorX - 1, iCursorY, " " ); kSetCursor( iCursorX - 1, iCursorY ); iCommandBufferIndex--; } } else if( bKey == KEY_ENTER ) { kPrintf( "\n" ); if( iCommandBufferIndex > 0 ) { // 커맨드 버퍼에 있는 명령을 실행 vcCommandBuffer[ iCommandBufferIndex ] = '\0'; kExecuteCommand( vcCommandBuffer ); } // 프롬프트 출력 및 커맨드 버퍼 초기화 kPrintf( "%s", CONSOLESHELL_PROMPTMESSAGE ); kMemSet( vcCommandBuffer, '\0', CONSOLESHELL_MAXCOMMANDBUFFERCOUNT ); iCommandBufferIndex = 0; } // 시프트 키, CAPS Lock, NUM Lock, Scroll Lock은 무시 else if( ( bKey == KEY_LSHIFT ) || ( bKey == KEY_RSHIFT ) || ( bKey == KEY_CAPSLOCK ) || ( bKey == KEY_NUMLOCK ) || ( bKey == KEY_SCROLLLOCK ) ) { ; } else if( bKey < 128 ) { // TAB은 공백으로 전환 if( bKey == KEY_TAB ) { bKey = ' '; } // 버퍼가 남아있을 때만 가능 if( iCommandBufferIndex < CONSOLESHELL_MAXCOMMANDBUFFERCOUNT ) { vcCommandBuffer[ iCommandBufferIndex++ ] = bKey; kPrintf( "%c", bKey ); } } } }
/** * 셸의 메인 루프 */ void kStartConsoleShell( void ) { char vcCommandBuffer[ CONSOLESHELL_MAXCOMMANDBUFFERCOUNT ]; int iCommandBufferIndex = 0; BYTE bKey; int iCursorX, iCursorY; // 프롬프트 출력 kPrintf( CONSOLESHELL_PROMPTMESSAGE ); while( 1 ) { // 키가 수신될 때까지 대기 bKey = kGetCh(); // Backspace 키 처리 if( bKey == KEY_BACKSPACE ) { if( iCommandBufferIndex > 0 ) { // 현재 커서 위치를 얻어서 한 문자 앞으로 이동한 다음 공백을 출력하고 // 커맨드 버퍼에서 마지막 문자 삭제 kGetCursor( &iCursorX, &iCursorY ); kPrintStringXY( iCursorX - 1, iCursorY, " " ); kSetCursor( iCursorX - 1, iCursorY ); iCommandBufferIndex--; } } // 엔터 키 처리 else if( bKey == KEY_ENTER ) { kPrintf( "\n" ); if( iCommandBufferIndex > 0 ) { // 커맨드 버퍼에 있는 명령을 실행 vcCommandBuffer[ iCommandBufferIndex ] = '\0'; kExecuteCommand( vcCommandBuffer ); } // 프롬프트 출력 및 커맨드 버퍼 초기화 kPrintf( "%s", CONSOLESHELL_PROMPTMESSAGE ); kMemSet( vcCommandBuffer, '\0', CONSOLESHELL_MAXCOMMANDBUFFERCOUNT ); iCommandBufferIndex = 0; } // 시프트 키, CAPS Lock, NUM Lock, Scroll Lock은 무시 else if( ( bKey == KEY_LSHIFT ) || ( bKey == KEY_RSHIFT ) || ( bKey == KEY_CAPSLOCK ) || ( bKey == KEY_NUMLOCK ) || ( bKey == KEY_SCROLLLOCK ) ) { ; } else { // TAB은 공백으로 전환 if( bKey == KEY_TAB ) { bKey = ' '; } // 버퍼에 공간이 남아있을 때만 가능 if( iCommandBufferIndex < CONSOLESHELL_MAXCOMMANDBUFFERCOUNT ) { vcCommandBuffer[ iCommandBufferIndex++ ] = bKey; kPrintf( "%c", bKey ); } } } }
//============================================================================= // Code for shell //============================================================================= // Main loop void kStartConsoleShell( void ) { char vcCommandBuffer[CONSOLESHELL_MAXCOMMANDBUFFERCOUNT]; int iCommandBufferIndex = 0; BYTE bKey; int iCursorX, iCursorY; // Print prompt kPrintf( CONSOLESHELL_PROMPTMESSAGE ); while( 1 ) { // Wait for key bKey = kGetCh(); // If backspace if ( bKey == KEY_BACKSPACE ) { if ( iCommandBufferIndex > 0 ) { // Get current cursor point, move back on point // print white space, // delete last character in command buffer kGetCursor( &iCursorX, &iCursorY ); kPrintStringXY( iCursorX - 1, iCursorY, " " ); kSetCursor( iCursorX - 1, iCursorY ); iCommandBufferIndex--; } } // Process enter key else if ( bKey == KEY_ENTER ) { kPrintf( "\n" ); if ( iCommandBufferIndex > 0 ) { // Execute command in buffer vcCommandBuffer[iCommandBufferIndex] = '\0'; kExecuteCommand( vcCommandBuffer ); } // Print prompt and Initialize command buffer kPrintf( "%s", CONSOLESHELL_PROMPTMESSAGE ); kMemSet( vcCommandBuffer, '\0', CONSOLESHELL_MAXCOMMANDBUFFERCOUNT ); iCommandBufferIndex = 0; } // Ignore Shift key, Caps lock, Num lock, Scroll lock else if ( ( bKey == KEY_LSHIFT ) || ( bKey == KEY_RSHIFT ) || ( bKey == KEY_CAPSLOCK ) || ( bKey == KEY_NUMLOCK ) || ( bKey == KEY_SCROLLLOCK ) ) { ; } else { // Switch TAB to white space if ( bKey == KEY_TAB ) { bKey = ' '; } // If buffer have room if ( iCommandBufferIndex < CONSOLESHELL_MAXCOMMANDBUFFERCOUNT ) { vcCommandBuffer[iCommandBufferIndex++] = bKey; kPrintf( "%c", bKey ); } } } }