BOOL kWaitForACKAndPutOtherScanCode( void ) { int i, j; BYTE bData; BOOL bResult = FALSE; // 100번 꺼내본다. (이전에 들어온 키보드 신호때문에) for( j = 0 ; j < 100 ; j++ ) { // 올때까지 0xFFFF번 실행 for( i = 0 ; i < 0xFFFF ; i++ ) { if( kIsOutputBufferFull() ) // outputbuffer에 ACK 신호가 있으면 데이터 읽어내야 함 { break; } } bData = kInPortByte(0x60); if( bData == 0xFA ) { bResult = TRUE; break; } else { kConvertScanCodeAndPutQueue( bData ); } } return bResult; }
/** * ACK를 기다림 * ACK가 아닌 다른 스캔 코드는 변환해서 큐에 삽입 */ BOOL kWaitForACKAndPutOtherScanCode( void ) { int i, j; BYTE bData; BOOL bResult = FALSE; // ACK가 오기 전에 키보드 출력 버퍼(포트 0x60)에 키 데이터가 저장되어 있을 수 있으므로 // 키보드에서 전달된 데이터를 최대 100개까지 수신하여 ACK를 확인 for( j = 0 ; j < 100 ; j++ ) { // 0xFFFF만큼 루프를 수행할 시간이면 충분히 커맨드의 응답이 올 수 있음 // 0xFFFF 루프를 수행한 이후에도 출력 버퍼(포트 0x60)가 차 있지 않으면 무시하고 읽음 for( i = 0 ; i < 0xFFFF ; i++ ) { // 출력 버퍼(포트 0x60)가 차있으면 데이터를 읽을 수 있음 if( kIsOutputBufferFull() == TRUE ) { break; } } // 출력 버퍼(포트 0x60)에서 읽은 데이터가 ACK(0xFA)이면 성공 bData = kInPortByte( 0x60 ); if( bData == 0xFA ) { bResult = TRUE; break; } // ACK(0xFA)가 아니면 키보드 큐에 삽입 else { kConvertScanCodeAndPutQueue( bData ); } } 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 }
BOOL kIsInputBufferFull(void) // 입력 버퍼에 내용이 있는가? { if (kInPortByte(0x64) & 0x02) { return TRUE; } return FALSE; }
BOOL kIsOutputBufferFull(void) // 출력 버퍼에 내용이 있는가? { if (kInPortByte(0x64) & 0x01) // 0x64 포트를 읽어서 0x01이 셋팅 되어 있으면 출력버퍼 안가져감 { return TRUE; } return FALSE; }
// 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; }
/** * 출력 버퍼(포트 0x60)에서 키를 읽음 */ BYTE kGetKeyboardScanCode( void ) { // 출력 버퍼(포트 0x60)에 데이터가 있을 때까지 대기 while( kIsOutputBufferFull() == FALSE ) { ; } return kInPortByte( 0x60 ); }
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 ); }
BYTE kGetKeyboardScanCode( void ) { while( !kIsOutputBufferFull() ) { // 출력 버퍼에 아무것도 없으면 무한루프 } return kInPortByte(0x60); }
/** * 입력 버퍼(포트 0x60)에 프로세서가 쓴 데이터가 남아있는지 여부를 반환 */ BOOL kIsInputBufferFull( void ) { // 상태 레지스터(포트 0x64)에서 읽은 값에 입력 버퍼 상태 비트(비트 1)가 // 1로 설정되어 있으면 아직 키보드가 데이터를 가져가지 않았음 if( kInPortByte( 0x64 ) & 0x02 ) { return TRUE; } return FALSE; }
/** * 출력 버퍼(포트 0x60)에 수신된 데이터가 있는지 여부를 반환 */ BOOL kIsOutputBufferFull( void ) { // 상태 레지스터(포트 0x64)에서 읽은 값에 출력 버퍼 상태 비트(비트 0)가 // 1로 설정되어 있으면 출력 버퍼에 키보드가 전송한 데이터가 존재함 if( kInPortByte( 0x64 ) & 0x01 ) { return TRUE; } return FALSE; }
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 ); }
/** * 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 ); }