Welcome to My World (www.dgmayor.com)

소프트웨어/C & 자료구조 & 커널 & DB

20. 하드디스크 드라이버 쓰기

dgmayor 2022. 6. 14. 11:26
728x90
 

20강 소스코드입니다.
 

--------------------------------------------------------------------------------
 

안녕하세요
 
오늘은 하드디스크에 쓰는 함수를 구현해봅시다.
 
논리는 하드디스크를 읽었을 때와 똑같습니다. 다른 점은 하드디스크에 내릴 명령이 읽기(0x20) 이 아니라 쓰기(0x30)인 점, 그리고 쓸 때 명령어 "rep outsw " 를 사용할 것이라는 점입니다.
 
바로 코드를 봅시다. 19강에 짰던 코드와 거의 차이가 없음을 알 수 있을 겁니다.
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
void HDDwrite(unsigned int sector, char* buffer)
{
 
    unsigned char LBA_a = sector & 0xFF// sector의 [7:0] 비트 추출
    unsigned char LBA_b = (sector >> 8& 0xFF// sector의 [15:8] 비트 추출
    unsigned char LBA_c = (sector >> 16& 0xFF// sector의 [23:16] 비트 추출
    unsigned char LBA_d = ((sector >> 24& 0x0F| 0xE0// sector의 [27:24] 비트 추출
 
    // HDD INT 활성화
    __asm__ __volatile__
    (
        "mov al, 0;"
        "mov dx, 0x3F6;"
        "out dx, al;"
    );
 
    while (HDD_BSY() == 1); // HDD가 busy 하다면 계속 대기
 
    /////////////////////////////////////////////////
    // 하드디스크 셋팅 시작
    /////////////////////////////////////////////////
 
    // 드라이브/헤드 레지스터 초기화 + LBA 주소 [27:24] 4비트
    __asm__ __volatile__
    (
        "mov al, %0;"
        "mov dx, 0x1F6;"
        "out dx, al;"::"r"(LBA_d)
    );
 
    __asm__ __volatile__
    (
        "mov al, 0x01;"
        "mov dx,0x1F2;"
        "out dx, al;"
    ); // 섹터 1개 쓴다
 
    __asm__ __volatile__
    (
        "mov al, %0;"
        "mov dx,0x1F3;"
        "out dx, al;" ::"r"(LBA_a)
    ); // LBA 주소 [7:0] 8비트
 
    __asm__ __volatile__
    (
        "mov al, %0;"
        "mov dx,0x1F4;"
        "out dx, al;" ::"r"(LBA_b)
    ); // LBA 주소 [15:8] 8비트
 
    __asm__ __volatile__
    (
        "mov al, %0;"
        "mov dx,0x1F5;"
        "out dx, al;" ::"r"(LBA_c)
    ); // LBA 주소 [23:16] 8비트
 
       /////////////////////////////////////////////////
       // 하드디스크 셋팅 끝
       /////////////////////////////////////////////////
 
 
       // 쓰기(0x30) 내리기 전 하드디스크 드라이버가 명령을 받을 수 있는지 체크
    while ((HDD_BSY() == 1|| (HDD_DRDY() == 0));
 
 
    // 쓰기(0x30) 명령 내리기
    __asm__ __volatile__
    (
        "mov al, 0x30;"
        "mov dx,0x1F7;"
        "out dx, al;"
    );
 
    // 명령 내렸는데 오류가 발생했다면 쓰기를 중단한다.
    if (HDD_ERR() == 1)
    {
        kprintf("Error!!", videomaxline - 10);
        return;
    }
 
    while (HDD_DRQ() == 0); // 데이터를 쓸 때까지 대기
 
 
    //  Buffer의 512바이트만큼 데이터를 메모리(0x1F0)에 쓴다
    __asm__ __volatile__("mov dx,0x1F0;");
    __asm__ __volatile__("mov esi, %0;" : : "r"(buffer));
    __asm__ __volatile__("mov ecx, 256");
    __asm__ __volatile__("rep outsw");
 
 
}
 
cs

 

좋습니다! 읽기때와 마찬가지로 제대로 실행되는지 알 수가 없으니 이를 검증하는 간단한 Shell 명령어를 추가합시다.
 
 
1
2
3
4
5
6
7
8
9
10
// shell.c 에 추가
void sh_HDDwrite()
{
 
    unsigned char test[512= "Hello world!";
 
    HDDwrite(2, test);
    HDDwrite(3, test);
 
}
cs

 
1
2
3
4
5
6
7
8
9
10
11
12
// main.c의 함수 수정
void translate_shell()
{
    if (keyboard[0== 0) { return; } // 명령어 없이 그냥 ENTER 침
    if (kstrcmp(keyboard, "clear")) { sh_clear(); return; }
    if (kstrcmp(keyboard, "version")) { sh_version(); return; }
    if (kstrcmp(keyboard, "read")) { sh_HDDread(); return; }
    if (kstrcmp(keyboard, "write")) { sh_HDDwrite(); return; }
    
    kprintf("There is no such command.",++curline, 0);
}
 
cs
 
 

이렇게 함수를 추가하면 "write" 입력시 하드디스크의 2번째 섹터와 3번째 섹터에 각각 Hello world 가 저장될 겁니다.
 
좋습니다! 이제 바로 컴파일해보고 Qemu로 돌려봅시다. 그 전에 하드디스크에 해당하는 hdd.img의 섹터 2, 섹터 3을 먼저 체크해봅시다.
 
 
 

보다시피 아무것도 없습니다. 이제 Qemu 상에 write 명령을 입력합시다. 하드디스크를 읽었을 때와 마찬가지로 쓸 때도 인터럽트가 발생합니다. 따라서 idt_ignore 가 아래에 찍혀나옵니다. 그리고 아무것도 출력하지 않게 해놓았으니 아무 반응 없을 겁니다.
 
 
 
 
좋습니다. 이제 환경을 끄고 다시 hdd.img를 확인합시다!
 
 
 
 
예상대로 섹터 2와 섹터 3의 첫 줄에 Hello world! 가 저장되어 있는 것을 확인할 수 있습니다. 이렇게 간단하게 하드디스크에 쓰는 함수를 구현했습니다!! 드디어 HoGoS 에서도 자료를 하드디스크에 저장할 수 있게 된 겁니다.
 
이를 극대화하기 위해선 파일시스템이 절대적으로 필요합니다. 다음 강의에서는 이를 다뤄보도록 하겠습니다. 파일시스템이 완성된다면 손쉽게 파일을 읽고 쓸 수 있게 됩니다!
 
감사합니다.
728x90