/** * 프로세서를 리셋(Reset) */ void kReboot( void ) { int i; // 입력 버퍼(포트 0x60)에 데이터가 비어있으면 출력 포트에 값을 쓰는 커맨드와 출력 포트 데이터 전송 for( i = 0 ; i < 0xFFFF ; i++ ) { // 입력 버퍼(포트 0x60)가 비었으면 커맨드 전송 가능 if( kIsInputBufferFull() == FALSE ) { break; } } // 커맨드 레지스터(0x64)에 출력 포트 설정 커맨드(0xD1)을 전달 kOutPortByte( 0x64, 0xD1 ); // 입력 버퍼(0x60)에 0을 전달하여 프로세서를 리셋(Reset)함 kOutPortByte( 0x60, 0x00 ); while( 1 ) { ; } }
/** * 키보드를 활성화 함 */ 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; }
void kEnableA20Gate( void ) { BYTE bOutputPortData; int i; // 키보드 컨트롤러 정보를 읽거나 쓰려면 미리 D0, D1 커맨드 신호를 보내야 한다. kOutPortByte( 0x64, 0xD0 ); // 키보드 컨트롤러의 출력 포트 값을 읽는 함수 for( i = 0 ; i < 0xFFFF ; i++ ) { if( kIsOutputBufferFull()) // 출력값이 있으면 { break; } } bOutputPortData = kInPortByte(0x60); // 출력값을 읽어냄 bOutputPortData |= 0x01; // 1인경우 A20Gate, 0인경우 리붓 for( i = 0 ; i < 0xFFFF ; i++ ) { if ( kIsInputBufferFull() == FALSE ) // 입력 버퍼에 데이터가 비어있으면 { break; } } kOutPortByte(0x64, 0xD1); // 키보드 컨트롤러의 출력 포트 값을 보내는 커맨드 kOutPortByte(0x60, bOutputPortData); // A20 Gate On }
/** * 커서의 위치를 설정 * 문자를 출력할 위치도 같이 설정 */ void kSetCursor( int iX, int iY ) { int iLinearValue; int iOldX; int iOldY; int i; // 커서의 위치를 계산 iLinearValue = iY * CONSOLE_WIDTH + iX; // 텍스트 모드로 시작했으면 CRT 컨트롤러로 커서 위치를 전송 if( kIsGraphicMode() == FALSE ) { // CRTC 컨트롤 어드레스 레지스터(포트 0x3D4)에 0x0E를 전송하여 // 상위 커서 위치 레지스터를 선택 kOutPortByte( VGA_PORT_INDEX, VGA_INDEX_UPPERCURSOR ); // CRTC 컨트롤 데이터 레지스터(포트 0x3D5)에 커서의 상위 바이트를 출력 kOutPortByte( VGA_PORT_DATA, iLinearValue >> 8 ); // CRTC 컨트롤 어드레스 레지스터(포트 0x3D4)에 0x0F를 전송하여 // 하위 커서 위치 레지스터를 선택 kOutPortByte( VGA_PORT_INDEX, VGA_INDEX_LOWERCURSOR ); // CRTC 컨트롤 데이터 레지스터(포트 0x3D5)에 커서의 하위 바이트를 출력 kOutPortByte( VGA_PORT_DATA, iLinearValue & 0xFF ); }
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; }
/** * 키보드 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; }
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; }
void kReboot( void ) { int i; for(i = 0 ; i < 0xFFFF ; i++ ) { if( kIsInputBufferFull() == FALSE) break; } kOutPortByte(0x64, 0xD1); // 키보드 버퍼에 컨트롤 입력값을 입력할것이다. kOutPortByte(0x60, 0x00); while(1) { ; // 재부팅 } }
// Initialize PIT void kInitializePIT( WORD wCount, BOOL bPeriodic ) { // Initiate PIT controller register(port 0x43) // and stop it, then set binary counter as mode 0 kOutPortByte( PIT_PORT_CONTROL, PIT_COUNTER0_ONCE ); // If it is periodic, set mode 2 if ( bPeriodic == TRUE ) { // Set binary counter as mode 2 in PIT controller register(port 0x43) kOutPortByte( PIT_PORT_CONTROL, PIT_COUNTER0_PERIODIC ); } // Set initial value from LSB to MSB in counter0(port 0x40) kOutPortByte( PIT_PORT_COUNTER0, wCount ); kOutPortByte( PIT_PORT_COUNTER0, wCount >> 8 ); }
void kReadRTCTime( BYTE* pbHour, BYTE* pbMinute, BYTE* pbSecond ) { BYTE bData; // CMOS 메모리 어드레스 레지스터(포트 0x70)에 시간을 저장하는 레지스터 지정 kOutPortByte( RTC_CMOSADDRESS, RTC_ADDRESS_HOUR ); // 데이터 레지스터에서 시간 얻어옴 bData = kInPortByte( RTC_CMOSDATA ); *pbHour = RTC_BCDTOBINARY( bData ); kOutPortByte( RTC_CMOSADDRESS, RTC_ADDRESS_MINUTE ); bData = kInPortByte( RTC_CMOSDATA ); *pbMinute = RTC_BCDTOBINARY( bData ); kOutPortByte( RTC_CMOSADDRESS, RTC_ADDRESS_SECOND ); bData = kInPortByte( RTC_CMOSDATA ); *pbSecond = RTC_BCDTOBINARY( bData ); }
/** * A20 게이트를 활성화 */ void kEnableA20Gate( void ) { BYTE bOutputPortData; int i; // 컨트롤 레지스터(포트 0x64)에 키보드 컨트롤러의 출력 포트 값을 읽는 커맨드(0xD0) 전송 kOutPortByte( 0x64, 0xD0 ); // 출력 포트의 데이터를 기다렸다가 읽음 for( i = 0 ; i < 0xFFFF ; i++ ) { // 출력 버퍼(포트 0x60)가 차있으면 데이터를 읽을 수 있음 if( kIsOutputBufferFull() == TRUE ) { break; } } // 출력 포트(포트 0x60)에 수신된 키보드 컨트롤러의 출력 포트 값을 읽음 bOutputPortData = kInPortByte( 0x60 ); // A20 게이트 비트 설정 bOutputPortData |= 0x01; // 입력 버퍼(포트 0x60)에 데이터가 비어있으면 출력 포트에 값을 쓰는 커맨드와 출력 포트 데이터 전송 for( i = 0 ; i < 0xFFFF ; i++ ) { // 입력 버퍼(포트 0x60)가 비었으면 커맨드 전송 가능 if( kIsInputBufferFull() == FALSE ) { break; } } // 커맨드 레지스터(0x64)에 출력 포트 설정 커맨드(0xD1)을 전달 kOutPortByte( 0x64, 0xD1 ); // 입력 버퍼(0x60)에 A20 게이트 비트가 1로 설정된 값을 전달 kOutPortByte( 0x60, bOutputPortData ); }
/** * 커서의 위치를 설정 * 문자를 출력할 위치도 같이 설정 */ void kSetCursor( int iX, int iY ) { int iLinearValue; // 커서의 위치를 계산 iLinearValue = iY * CONSOLE_WIDTH + iX; // CRTC 컨트롤 어드레스 레지스터(포트 0x3D4)에 0x0E를 전송하여 // 상위 커서 위치 레지스터를 선택 kOutPortByte( VGA_PORT_INDEX, VGA_INDEX_UPPERCURSOR ); // CRTC 컨트롤 데이터 레지스터(포트 0x3D5)에 커서의 상위 바이트를 출력 kOutPortByte( VGA_PORT_DATA, iLinearValue >> 8 ); // CRTC 컨트롤 어드레스 레지스터(포트 0x3D4)에 0x0F를 전송하여 // 하위 커서 위치 레지스터를 선택 kOutPortByte( VGA_PORT_INDEX, VGA_INDEX_LOWERCURSOR ); // CRTC 컨트롤 데이터 레지스터(포트 0x3D5)에 커서의 하위 바이트를 출력 kOutPortByte( VGA_PORT_DATA, iLinearValue & 0xFF ); // 문자를 출력할 위치 업데이트 gs_stConsoleManager.iCurrentPrintOffset = iLinearValue; }
void kReadRTCDate( WORD* pwYear, BYTE* pbMonth, BYTE* pbDayOfMonth, BYTE* pbDayOfWeek ) { BYTE bData; kOutPortByte( RTC_CMOSADDRESS, RTC_ADDRESS_YEAR ); bData = kInPortByte( RTC_CMOSDATA ); *pwYear = RTC_BCDTOBINARY( bData ) + 2000; kOutPortByte( RTC_CMOSADDRESS, RTC_ADDRESS_MONTH ); bData = kInPortByte( RTC_CMOSDATA ); *pbMonth = RTC_BCDTOBINARY( bData ); kOutPortByte( RTC_CMOSADDRESS, RTC_ADDRESS_DAYOFMONTH ); bData = kInPortByte( RTC_CMOSDATA ); *pbDayOfMonth = RTC_BCDTOBINARY( bData ); kOutPortByte( RTC_CMOSADDRESS, RTC_ADDRESS_DAYOFWEEK ); bData = kInPortByte( RTC_CMOSDATA ); *pbDayOfWeek = RTC_BCDTOBINARY( bData ); }
// Return value of counter0 WORD kReadCounter0( void ) { BYTE bHighByte, bLowByte; WORD wTemp = 0; // Send latch command to PIT control register(port 0x43) to read value of counter0 kOutPortByte( PIT_PORT_CONTROL, PIT_COUNTER0_LATCH); // Read from LSB to MSB in counter0 bLowByte = kInPortByte( PIT_PORT_COUNTER0); bHighByte = kInPortByte( PIT_PORT_COUNTER0 ); // Return 16 bit wTemp = bHighByte; wTemp = ( wTemp << 8 ) | bLowByte; return wTemp; }
/** * 멀티코어 프로세서 또는 멀티 프로세서 모드로 전환하는 함수 */ 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; }