전번에 IDT를 구성하고 커널까지 컴파일 하고 부팅까지 해 보았다. 물론 아무런 기능도(?) 넣지 않아 눈으로 보기에는 아무 변화도 없었다. 재부팅 안하는게 어디야~~~. 우선 인터럽트 동작이 잘 동작 하는지 확인 해 보는 코드를 넣어서 내가 만든게 잘 동작하는지 확인해 보잣!!!! 아자~


int  StartKernel(int argc, char *argv[])
{
	char *hello = "Hello OS!";
	char *complete = "complete.";
	unsigned char* vidmem = (unsigned char*)0xB8000;
	unsigned char data = 0;
	int b = 5;
	int c = 0;


	printf(hello);

	InitPIC();
	Init_IDT();

	b = b/0;
	
	while(1) ;
	return 0;
}


void _declspec(naked) interrupt_handler()
{
	_asm pushad;

	printf("interrupt handler");
	_asm {
		popad
		iretd
	}		
}

인터럽트 중에 0으로 나누면 예외상황 인터럽트가 발생하는 인터럽트가 있었다. 그래서 0으로 나누면 분명히 인터럽트가 발생 할것이고 interrupt_handler함수에서 인터럽트가 발생하면 interrupt handler라는 문구를 찍도록 해보았다. 자~~ 컴파일..

헉!!!!! interrupt handler!! 무한 출력 후 재부팅 된다.

결과야 어찌되었든 인터럽트가 발생하여 화면에 출력이 되었다는 거에 만족하자~~ ㅋㅋㅋㅋㅋ 대충 했는데도 된다… ㅋ 오늘은 확인 했으니 이만 잘까??? 음… 뭐 IDT를 구현하게 된데에는 키보드 입력 받아서 출력 하는데 목적을 두었으니 키보드로 입력하면 키출력 하는데까지 하고 자야 겠다.

우선 0으로 나누는 부분을 지우고!~ 

키가 눌려지면 interrupt_handler함수가 호출 될테고 전번 포스팅 에서 했었던 것 처럼 0x60 포트를 읽으면 될것이다. 그러면 기존 코드를 붙여서..


void _declspec(naked) interrupt_handler()
{
	char keycode;

	_asm pushad;


	keycode = Read_port_byte(0x60);
	if(keycode >= 0 )
	{
		putc((char)kbd_scancode[keycode]);
	}
	_asm {
		popad
		iretd
	}		
}

짠,,… 컴파일은 잘 된다… 자 그럼!~

5..4..3..2..1 ……. 음… 안돼! 키 입력해도 아무런 변화가 없어!~~

왜???????????????????????????????????????????????????????????????????????????

IDT가 잘못 구성 되었나?? ….

소스를 봐도 뭐가 잘못 된 건지 모르겠다.. 디버깅도 안되고…ㅠㅠ 키보드 관련 검색부터 해보자..흠..

아….INIT_PIC함수에서 잘못 되었나? 그러고 보니 하드웨어 인터럽트 즉.. 8259 PIC는 하드웨어 인터럽트와 충돌이 나서 주소를 옮겨야 된다고 했다. 안 옮겨줬나?? 아닌데… 키보드 입력 되었는데… 너무 인터넷에서 긁어서 복사만 했나~~~ 흠. 그러면 다시 INIT_PIC 함수를 분석해보자 ..

void InitPIC()
{
	 
	Write_port_byte(0x20, 0x11);       
	Write_port_byte(0x21, 0x20);       
	Write_port_byte(0x21, 0x04);       
	Write_port_byte(0x21, 0x01);       
	Write_port_byte(0x21, 0xFF);         

	
	Write_port_byte(0xA0, 0x11);       
	Write_port_byte(0xA1, 0x28);       
	Write_port_byte(0xA1, 0x02);       
	Write_port_byte(0xA1, 0x01);       
	Write_port_byte(0xA1, 0xFF);        
}
      

Write_port_byte 함수야.. 뭐..첫번째 인자는 포트이고 두번째는 데이터…라는 것이고

0x20 포트에 0x11 데이터를 쓴다…. 왜?? 음.. 그냥 첫번째 PIC 아니 마스터 PIC 너를 초기화 할것이다. 라는 의미인것 같다.

Write_port_byte(0x21, 0x20) 이건 너의 인터럽트 시작 주소는 0x20 이다 라고 지정해주는 것이고.
Write_port_byte(0x21, 0x04) 요것은 음.. 마스터 PIC 3번째하고 슬레이브 PIC가 연결되어 있다라는걸 설정하는 것이란다. 3번째 인데 왜 4냐고?? PIC는 8개 비트로 구성되어 있는데~~~ 3번재 연결 핀이..

8bit 7bit 6bit 5bit 4bit 3bit 2bit 1bit
          1    

4가 된다..
Write_port_byte(0x21, 0x01) 이것은 8086 모드라는 것인데… 모르겠다.. 1로 설정 할 경우는 8086. 0인경우 80/85 모드라는데 .. 모르겠다. ㅡㅡ;;;;

Write_port_byte(0x21, 0xFF) ?????? 마스터 PIC 에서 모든 인터럽트를 막는다????? 이것 때문에 키보드가 입력 안되었던 것인가

Write_port_byte(0xA0, 0x11)  슬레이브 PIC 너를 초기화 해주겠어
Write_port_byte(0xA1, 0x28)  인터럽트 시작주소는 28 이다…
Write_port_byte(0xA1, 0x02);  넌 마스터PIC와 두번째 핀과 연결되어 있다.
Write_port_byte(0xA1, 0x01)  ?? 8086 ㅡㅡ;;;;;
Write_port_byte(0xA1, 0xFF)   모든 인터럽트를 막는다!!!!

그러니까… 저기 뻘건색으로 줄쳐진 이놈들 때문에 키보드가 동작하지 않은 것인가??? 왜???? 왜 막아야 하는건가??? 모르겠다… 지랄같은 영어.. 여튼.. 키보드는 마스터 PIC 두번째 핀에 연결되어 있다고 하니 0xFF를 0xFD로 바꿔보자… 그리고 컴파일 . 확인.

오!!!!!!!!!!!!!!

보라… Hello OS! 옆에 작은 a 으흐흐흐 동작한다… IDT 구성은 문제 없고 키보드 인터럽트도 잘 받고…??? 어라 그런데 한번만 입력된다…. 검색해보니 이러더라 EOI 를 보내라고 …. 그냥 EOI를 보내서 PIC 를 리셋 시켜야 된다고 한다.  마스터 PIC에서 인터럽트가 발생했으면 0x20 포트에다가 보내고… 슬레이브 PIC에서 발생했으면 0xA0과 , 마스터 PIC 0x20 둘다 보내야 한다고 한다. 그러면 인터럽트가 발생하면 발생한 인터럽트 IRQ를 알아야 마스터인지 슬래이브 인지 아는것 아닌가…흠… CPU가 인자로 넘겨주나??? 그런가 보다.. 넘겨주는 듯… 귀찮으니 우선은 키보드만 입력 받고… EOI를 보내라고 했으니 마스터PIC에 0x20을 보내고 다시 테스트.

흠…

잘 된다..


 

 

8042 키보드 컨트롤러

모르는건 인터넷에서 검색하다가 그것마저 귀찮으면 소스 찾아서 긁어서 사용하다 보니, 진행하다 보면 이게 뭐지? 하는 내용들이 종종 생긴다. “이것까지 내가 알아야 하나?” 하고 어물쩡 넘어갔는데 그런게 너무 반복 되다 보니  “내가 지금 뭐하고 있지?” 라는 생각이 요즘 많이 든다. 단순히 OS 만들것이면 인터넷에 널려 있는 소스들 수정해서 만들면 된다. 그냥 내가 목표로 하는 OS만 결과로 던져 내면 되는 것이다.  자… 그러면 난 지금 무엇을 하고 있는 것인가? OS를 만드는 것인가… OS를 만들기 위해서 공부를 하고 있는 것인가… 흠 그러다가 OS 만들기의 대단원의 시작인 첫 포스팅 글을 방금 다시 한번 찾아봤다.

OS를 만들기 위해 부랴부랴 인터넷 검색을 해봤다. 우와! 책도 많고 관련 정보들이 상당하다. 수준급인 OS 부터 기초 정보 또한 대단히 많다. ‘그냥 이거 가져다 수정하면서 공부해 보면 되겠네…’ 라고 생각했다가 접었다.. 왜? 내 코드가 아니고 내 구조가 아니고… 내 영혼(?)이 아니다. 그냥 하나 하나 내가 부딪치며 만들어야 내것 같다는 생각이 들어서다. 또 뭔가 고비가 있어야 내 지식이지, 단순히 복사 & 붙이기는 그냥 영혼없는 결과물 만들기일 뿐이라고 생각해서 이다.

ㅎㅎㅎ 무척 단순한 생각으로 시작했다. 남의 코드는 내것이 아니므로….^^ 영혼까지 언급했다.

복사 & 붙이기 로 결과물을 만들지 말자고 했는데 지금은 복사 & 붙이기 로 만들고 있다….. 그래… 다 공부해서 만들기로 했었지..~~~ㅎㅎㅎ

내가 왜 이런 심각한 고민을 하게 된건 , 8042 키보드 컨트롤러가 키보드 관련해서 검색해 보다가 등장해서 이다. 키보드에서 인터럽트가 발생하게 될 경우, 8259 에서 인터럽트를 CPU에 알리고 다시 0x60 포트에서 키 값을 읽으면 된다. 라는 이 부분에서 0x60 이 포트가 궁금해서 찾아보다가 찾았다. 그냥 0x60에서 키 값을 읽으면 된다 라고 하고 넘어갈까 말까 망설였었다. 왜?? 귀찮으니까~~~

ㅎㅎㅎㅎ

여하튼.. 그냥 하자!!!~~~~~~

키보드와 마우스는 시리얼 통신을 한다고 배웠고 그렇게 되어 있다고 한다. 이 키보드와 마우스는 우리가 쉽게 얘기하는 PS/2 라고 불리우는 8042 컨트롤러와 연결 되어 있고 말이다. 키보드/마우스 제어 외에도 앞선 포스팅에서 언급한 주소 확장 관련해서 A20 Enable 기능도 8042 컨트롤러가 제어한다고 한다.

위 그림은 8042와 8259PIC와 CPU 연결을 도식화 한 것이다. 키보드나 마우스 입력 시 8042는 8259 PIC 마스터나 슬레이브에 IRQ 신호를 보내고 8259는 이를 CPU에 보낸다. 또 CPU는 8042를 0x60 또는 0x64 포트를 통해 데이터를 읽던지 제어를 한다고 한다.

IO 포트

접근 구분

용도

0x60 Read/Write 데이터 읽고 쓰기
0x64 Read Status 읽기
0x64 Write 명령 요청

전번 포스팅에서 키보드에 데이터 입력이 있는지 없는지 알기 위해서 0x64 포트의 Status를 읽어서 사용한 적이 있었다.

또 키보드 관련해서 알아야 할 내용이 생겼다. Set1, Set2, Set3… 이게 뭐냐면.. IBM 에서 콤퓨타를 만들어 낼 때 마다 새로운 키보드 인터페이스를 만들었었는데 XT 키보드, AT 키보드, PS/2 키보드 등으로 구분된다고 한다. 또한 이 키보드 타입 들은 같은 문자에 따라 다른 값들을 보낸다고 한단다… 그래서 각 값들을 Set1, Set2, Set3에 맞게 찾아서 문자를 대입해야 한다고 한다. Set1은 XT , Set2는 AT, Set3은 PS/2.
내가 코드에서 사용했던 건 Set1 이다. 8042를 통해 현재 사용하고 있는 키보드의 인터페이스를 얻어 낼 수 있고 지정 할 수 있다고 한다.

음.. 8042 명령어들과 기능들도 있는데 이건 필요할 때 마다 참조 하는 것으로 하고 8042에 대해서 여기서 마쳐야 겠다.

+ Recent posts