����9-2 linux/kernel/blk_drv/hd.c


  1 /*

  2  *  linux/kernel/hd.c

  3  *

  4  *  (C) 1991  Linus Torvalds

  5  */

  6

  7 /*

  8  * This is the low-level hd interrupt support. It traverses the

  9  * request-list, using interrupts to jump between functions. As

 10  * all the functions are called within interrupts, we may not

 11  * sleep. Special care is recommended.

 12  *

 13  *  modified by Drew Eckhardt to check nr of hd's from the CMOS.

 14  */

    /*

     * �������ǵײ�Ӳ���жϸ���������Ҫ����ɨ����������У�ʹ���ж�

     * �ں���֮����ת���������еĺ����������ж�����õģ�������Щ����

     * ������˯�ߡ����ر�ע�⡣

     *

     * ��Drew Eckhardt�޸ģ�����CMOS��Ϣ���Ӳ������

     */

 15

 16 #include <linux/config.h> // �ں�����ͷ�ļ�������������Ժ�Ӳ�����ͣ�HD_TYPE��ѡ�

 17 #include <linux/sched.h>  // ���ȳ���ͷ�ļ�����������ṹtask_struct������0���ݵȡ�

 18 #include <linux/fs.h>     // �ļ�ϵͳͷ�ļ��������ļ����ṹ��file��m_inode���ȡ�

 19 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣

 20 #include <linux/hdreg.h>  // Ӳ�̲���ͷ�ļ�������Ӳ�̼Ĵ����˿ڡ�״̬�롢����������Ϣ��

 21 #include <asm/system.h>   // ϵͳͷ�ļ����������û��޸�������/�ж��ŵȵĻ��ꡣ

 22 #include <asm/io.h>       // ioͷ�ļ�������Ӳ���˿�����/���������䡣

 23 #include <asm/segment.h>  // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����

 24

    // ����Ӳ�����豸�ŷ��ų����������������У����豸�ű����ڰ���blk.h�ļ�֮ǰ�����塣

    // ��Ϊblk.h�ļ���Ҫ�õ�������ų���ֵ��ȷ��һЩ��������ط��ų����ͺꡣ

 25 #define MAJOR_NR 3        // Ӳ�����豸����3��

 26 #include "blk.h"          // ���豸ͷ�ļ��������������ݽṹ�����豸���ݽṹ�ͺ����Ϣ��

 27

    // ��CMOS�����꺯����

    // ��κ��ȡCMOS��Ӳ����Ϣ��outb_p��inb_p��include/asm/io.h�ж���Ķ˿���������ꡣ

    // ��init/main.c�ж�ȡCMOSʱ����Ϣ�ĺ���ȫһ����

 28 #define CMOS_READ(addr) ({ \

 29 outb_p(0x80|addr,0x70); \          // 0x70��д�˿ںţ�0x80|addr��Ҫ����CMOS�ڴ��ַ��

 30 inb_p(0x71); \                     // 0x71�Ƕ��˿ںš�

 31 })

 32

 33 /* Max read/write errors/sector */

    /* ÿ������/д�������������������� */

 34 #define MAX_ERRORS      7          // ��/дһ������ʱ������������������

 35 #define MAX_HD          2          // ϵͳ֧�ֵ����Ӳ������

 36

    // ����У������������

    // ��λ����ʱ��Ӳ���жϴ��������е��õ�����У������(311��)��

 37 static void recal_intr(void);

    // ��дӲ��ʧ�ܴ������ú�����

    // ����������������������ø�λ��־Ҫ��ִ�и�λӲ�̿����������������ԣ�242�У���

 38 static void bad_rw_intr(void);

 39

    // ����У����־���������˸ñ�־�������л����recal_intr()�Խ���ͷ�ƶ���0���档

 40 static int recalibrate = 0;

   // ��λ��־����������д����ʱ�����øñ�־��������ظ�λ�������Ը�λӲ�̺Ϳ�������

 41 static int reset = 0;

 42

 43 /*

 44  *  This struct defines the HD's and their types.

 45  */

    /* ����ṹ������Ӳ�̲��������� */

    // Ӳ����Ϣ�ṹ��Harddisk information struct����

    // ���ֶηֱ��Ǵ�ͷ����ÿ�ŵ�����������������дǰԤ��������š���ͷ��½������š�

    // �����ֽڡ����ǵĺ�����μ������б����˵����

 46 struct hd_i_struct {

 47         int head,sect,cyl,wpcom,lzone,ctl;

 48         };

 

    // ����Ѿ���include/linux/config.h�����ļ��ж����˷��ų���HD_TYPE����ȡ���ж���

    // �õIJ�����ΪӲ����Ϣ����hd_info[]�е����ݡ�������Ĭ�϶���Ϊ0ֵ����setup()����

    // �л����½������á�

 49 #ifdef HD_TYPE

 50 struct hd_i_struct hd_info[] = { HD_TYPE };                       // Ӳ����Ϣ���顣

 51 #define NR_HD ((sizeof (hd_info))/(sizeof (struct hd_i_struct)))  // ����Ӳ�̸�����

 52 #else

 53 struct hd_i_struct hd_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} };

 54 static int NR_HD = 0;

 55 #endif

 56

    // ����Ӳ�̷����ṹ������ÿ��������Ӳ��0����ʼ�����������ʼ�����źͷ�������������

    // ����5�ı������������hd[0]��hd[5]�ȣ���������Ӳ�̵IJ�����

 57 static struct hd_struct {

 58         long start_sect;                 // ������Ӳ���е���ʼ���������ԣ�������

 59         long nr_sects;                   // ����������������

 60 } hd[5*MAX_HD]={{0,0},};

 61

    // Ӳ��ÿ���������ݿ��������顣

 62 static int hd_sizes[5*MAX_HD] = {0, };

 63

    // ���˿�Ƕ����ꡣ���˿�port������nr�֣�������buf�С�

 64 #define port_read(port,buf,nr) \

 65 __asm__("cld;rep;insw"::"d" (port),"D" (buf),"c" (nr):"cx","di")

 66

    // д�˿�Ƕ����ꡣд�˿�port����дnr�֣���buf��ȡ���ݡ�

 67 #define port_write(port,buf,nr) \

 68 __asm__("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr):"cx","si")

 69

 

 70 extern void hd_interrupt(void);         // Ӳ���жϹ��̣�sys_call.s��235�У���

 71 extern void rd_load(void);              // �����̴������غ�����ramdisk.c��71�У���

 72

 73 /* This may be used only once, enforced by 'static int callable' */

    /* ����ú���ֻ�ڳ�ʼ��ʱ������һ�Ρ��þ�̬����callable��Ϊ�ɵ��ñ�־��*/

    // ϵͳ���ú�����

    // ��������BIOS���ɳ�ʼ������init/main.c��init�ӳ�������Ϊָ��Ӳ�̲������ṹ��ָ�롣

    // ��Ӳ�̲������ṹ����2��Ӳ�̲����������ݣ���32�ֽڣ����Ǵ��ڴ�0x90080�����ƶ�����

    // 0x90080����Ӳ�̲���������setup.s��������ROM BIOS����ȡ�á�Ӳ�̲�������Ϣ�μ�����

    // �б����˵���� ��������Ҫ�����Ƕ�ȡ CMOS��Ӳ�̲�������Ϣ����������Ӳ�̷����ṹhd��

    // �����Լ���RAM�����̺͸��ļ�ϵͳ��

 74 int sys_setup(void * BIOS)

 75 {

 76         static int callable = 1;                // ���Ʊ�����ֻ�ܱ�����1�εı�־��

 77         int i,drive;

 78         unsigned char cmos_disks;

 79         struct partition *p;

 80         struct buffer_head * bh;

 81

    // ��������callable��־��ʹ�ñ�����ֻ�ܱ�����1�Ρ�Ȼ������Ӳ����Ϣ����hd_info[]��

    // ����� include/linux/config.h �ļ����Ѷ����˷��ų���HD_TYPE����ô hd_info[]����

    // �Ѿ���ǰ���49�������ú��ˡ��������Ҫ��ȡboot/setup.s���������ڴ�0x90080��

    // ��ʼ��Ӳ�̲�������setup.s�������ڴ�˴����������һ������Ӳ�̲�������

 82         if (!callable)

 83                 return -1;

 84         callable = 0;

 85 #ifndef HD_TYPE                                  // ���û�ж���HD_TYPE�����ȡ��

 86         for (drive=0 ; drive<2 ; drive++) {

 87                 hd_info[drive].cyl = *(unsigned short *) BIOS;      // ��������

 88                 hd_info[drive].head = *(unsigned char *) (2+BIOS);  // ��ͷ����

 89                 hd_info[drive].wpcom = *(unsigned short *) (5+BIOS); // дǰԤ��������š�

 90                 hd_info[drive].ctl = *(unsigned char *) (8+BIOS);    // �����ֽڡ�

 91                 hd_info[drive].lzone = *(unsigned short *) (12+BIOS);// ��ͷ��½������š�

 92                 hd_info[drive].sect = *(unsigned char *) (14+BIOS);  // ÿ�ŵ���������

 93                 BIOS += 16;             // ÿ��Ӳ�̲�������16�ֽڣ�����BIOSָ����һ����

 94         }

    // setup.s������ȡBIOSӲ�̲�������Ϣʱ�����ϵͳ��ֻ��1��Ӳ�̣��ͻὫ��Ӧ��2��

    // Ӳ�̵�16�ֽ�ȫ�����㡣�������ֻҪ�жϵ�2��Ӳ���������Ƿ�Ϊ0�Ϳ���֪���Ƿ���

    // ��2��Ӳ���ˡ�

 95         if (hd_info[1].cyl)

 96                 NR_HD=2;               // Ӳ������Ϊ2��

 97         else

 98                 NR_HD=1;

 99 #endif

    // �����Ӳ����Ϣ����hd_info[]�Ѿ����úã�����ȷ����ϵͳ���е�Ӳ����NR_HD������

    // ��ʼ����Ӳ�̷����ṹ����hd[]�����������0����5 �ֱ��ʾ����Ӳ�̵������������

    // ��1��4��6��9�ֱ��ʾ����Ӳ�̵�4�������IJ����� �����������ñ�ʾӲ��������Ϣ

    // �������0��5����

100         for (i=0 ; i<NR_HD ; i++) {

101                 hd[i*5].start_sect = 0;                        // Ӳ����ʼ�����š�

102                 hd[i*5].nr_sects = hd_info[i].head*

103                                 hd_info[i].sect*hd_info[i].cyl;  // Ӳ������������

104         }

105

106         /*

107                 We querry CMOS about hard disks : it could be that

108                 we have a SCSI/ESDI/etc controller that is BIOS

109                 compatable with ST-506, and thus showing up in our

110                 BIOS table, but not register compatable, and therefore

111                 not present in CMOS.

112

113                 Furthurmore, we will assume that our ST-506 drives

114                 <if any> are the primary drives in the system, and

115                 the ones reflected as drive 1 or 2.

116

117                 The first drive is stored in the high nibble of CMOS

118                 byte 0x12, the second in the low nibble.  This will be

119                 either a 4 bit drive type or 0xf indicating use byte 0x19

120                 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.

121

122                 Needless to say, a non-zero value means we have

123                 an AT controller hard disk for that drive.

124

125                 

126         */

            /*

                    ���Ƕ�CMOS�й�Ӳ�̵���Ϣ��Щ���ɣ����ܻ���������������

                    ������һ��SCSI/ESDI/�ȵĿ�������������ST-506��ʽ��BIOS

                    ����ݵģ��������������ǵ�BIOS�������У���ȴ�ֲ��ǼĴ�

                    �����ݵģ������Щ������CMOS���ֲ����ڡ�

 

                    ���⣬���Ǽ���ST-506������������еĻ�����ϵͳ�еĻ�����

                    ������Ҳ����������1��2���ֵ���������

 

                    ��1�����������������CMOS�ֽ�0x12�ĸ߰��ֽ��У���2��

                    ����ڵͰ��ֽ��С���4λ�ֽ���Ϣ���������������ͣ�Ҳ����

                    ����0xf��0xf��ʾʹ��CMOS��0x19�ֽ���Ϊ������1��8λ

                    �����ֽڣ�ʹ��CMOS��0x1A�ֽ���Ϊ������2�������ֽڡ�

 

                    ��֮��һ������ֵ��ζ��Ӳ����һ��AT����������Ӳ�̡�

             */

127

    // �����������ԭ������������������Ӳ�̵����Dz���AT���������ݵġ��й�CMOS��Ϣ

    // ��μ���4����4.2.3.1�ڡ������CMOSƫ�Ƶ�ַ0x12������Ӳ�������ֽڡ�����Ͱ�

    // �ֽ�ֵ������ŵ�2��Ӳ������ֵ����Ϊ0�����ʾϵͳ����Ӳ�̣������ʾϵͳֻ��1

    // ��Ӳ�̡����0x12��������ֵΪ0�����ʾϵͳ��û��AT����Ӳ�̡�

128         if ((cmos_disks = CMOS_READ(0x12)) & 0xf0)

129                 if (cmos_disks & 0x0f)

130                         NR_HD = 2;

131                 else

132                         NR_HD = 1;

133         else

134                 NR_HD = 0;

    // ��NR_HD = 0��������Ӳ�̶�����AT���������ݵģ�����Ӳ�����ݽṹȫ���㡣

    // ��NR_HD = 1���򽫵�2��Ӳ�̵IJ������㡣

135         for (i = NR_HD ; i < 2 ; i++) {

136                 hd[i*5].start_sect = 0;

137                 hd[i*5].nr_sects = 0;

138         }

    // �ã�����Ϊֹ�����Ѿ�����ȷ����ϵͳ��������Ӳ�̸���NR_HD��������������ȡÿ��Ӳ��

    // �ϵ�1�������еķ�������Ϣ���������÷����ṹ����hd[] ��Ӳ�̸���������Ϣ��������

    // �ö��麯��bread()��Ӳ�̵�1�����ݿ飨fs/buffer.c����267�У�����1��������0x300��

    // 0x305 ���ֱ�������Ӳ�̵��豸�ţ���2��������0���������ȡ�Ŀ�š����������ɹ���

    // �����ݻᱻ����ڻ����bh���������С��������ͷָ��bhΪ0����˵��������ʧ�ܣ���

    // ��ʾ������Ϣ��ͣ�����������Ǹ���Ӳ�̵�1��������������ֽ�Ӧ����0xAA55���ж���

    // �������ݵ���Ч�ԣ��Ӷ�����֪��������λ��ƫ��0x1BE��ʼ���ķ������Ƿ���Ч������Ч

    // ��Ӳ�̷�������Ϣ����Ӳ�̷����ṹ����hd[]�С�����ͷ�bh��������

139         for (drive=0 ; drive<NR_HD ; drive++) {

140                 if (!(bh = bread(0x300 + drive*5,0))) {  // 0x300��0x305���豸�š�

141                         printk("Unable to read partition table of drive %d\n\r",

142                                 drive);

143                         panic("");

144                 }

145                 if (bh->b_data[510] != 0x55 || (unsigned char)

146                     bh->b_data[511] != 0xAA) {            // �ж�Ӳ�̱�־0xAA55��

147                         printk("Bad partition table on drive %d\n\r",drive);

148                         panic("");

149                 }

150                 p = 0x1BE + (void *)bh->b_data;    // ������λ�ڵ�1����0x1BE����

151                 for (i=1;i<5;i++,p++) {

152                         hd[i+5*drive].start_sect = p->start_sect;

153                         hd[i+5*drive].nr_sects = p->nr_sects;

154                 }

155                 brelse(bh);                 // �ͷ�Ϊ���Ӳ�����ݿ������Ļ�������

156         }

    // �����ٶ�ÿ�������е����ݿ���������ͳ�ƣ���������Ӳ�̷��������ݿ�����hd_sizes[]�С�

    // Ȼ�����豸���ݿ�����ָ������ı��豸��ָ������顣

157         for (i=0 ; i<5*MAX_HD ; i++)

158                 hd_sizes[i] = hd[i].nr_sects>>1 ;

159         blk_size[MAJOR_NR] = hd_sizes;

    // ���������������Ӳ�̷����ṹ����hd[]���������ȷʵ��Ӳ�̴��ڲ����Ѷ��������

    // ��������ʾ����������������Ϣ��Ȼ������ϵͳ�ڴ��������м����������а����ĸ���

    // ��ϵͳӳ��blk_drv/ramdisk.c����71�У�������ϵͳ�����������̵�������ж�������

    // ���Ƿ񻹺��и��ļ�ϵͳ��ӳ�����ݡ�����У���ʱ�������̳�Ϊ�����̣����԰Ѹ�ӳ��

    // ���ز���ŵ��������У�Ȼ��Ѵ�ʱ�ĸ��ļ�ϵͳ�豸��ROOT_DEV�޸ij������̵��豸�š�

    // �����ٶԽ����豸���г�ʼ�������װ���ļ�ϵͳ��

160         if (NR_HD)

161                 printk("Partition table%s ok.\n\r",(NR_HD>1)?"s":"");

162         rd_load();                          // blk_drv/ramdisk.c����71�С�

163         init_swapping();                    // mm/swap.c����199�С�

164         mount_root();                       // fs/super.c����241�С�

165         return (0);

166 }

167

    //// �жϲ�ѭ���ȴ�Ӳ�̿�����������

    // ��Ӳ�̿�����״̬�Ĵ����˿�HD_STATUS(0x1f7)��ѭ��������е���������������λ��λ6��

    // �Ƿ���λ���ҿ�����æλ��λ7���Ƿ񱻸�λ�� �������ֵretriesΪ0�����ʾ�ȴ�����

    // �����е�ʱ���Ѿ���ʱ����������������ֵ��Ϊ0��˵���ڵȴ���ѭ����ʱ�������ڿ�����

    // �ص�����״̬��OK��

    // ʵ���ϣ����ǽ�����״̬�Ĵ���æλ��λ7���Ƿ�Ϊ1���жϿ������Ƿ���æ״̬������

    // ���Ƿ��������λ6�Ƿ�Ϊ1�����������״̬�޹ء�������ǿ��԰ѵ�172������д�ɣ�

    // ��while (--retries && (inb_p(HD_STATUS)&0x80));�����⣬�������ڵ�PC���ٶȶ��ܿ죬

    // ������ǿ��԰ѵȴ���ѭ�������ټӴ�һЩ������������10����

168 static int controller_ready(void)

169 {

170         int retries = 100000;

171

172         while (--retries && (inb_p(HD_STATUS)&0xc0)!=0x40);

173         return (retries);                        // ���صȴ�ѭ��������

174 }

175

    //// ���Ӳ��ִ��������״̬����win ��ʾ����˹��Ӳ�̵���д��

    // ��ȡ״̬�Ĵ����е�����ִ�н��״̬�� ����0��ʾ������1��ʾ���������ִ���������

    // ����Ҫ�ٶ�����Ĵ���HD_ERROR��0x1f1����

176 static int win_result(void)

177 {

178         int i=inb_p(HD_STATUS);             // ȡ״̬��Ϣ��

179

180         if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT))

181                 == (READY_STAT | SEEK_STAT))

182                 return(0); /* ok */

183         if (i&1) i=inb(HD_ERROR);          // ��ERR_STAT��λ�����ȡ����Ĵ�����

184         return (1);

185 }

186

    //// ��Ӳ�̿�������������顣

    // ������drive - Ӳ�̺�(0-1)��nsect - ��д��������sect  - ��ʼ������

    //       head  - ��ͷ�ţ�     cyl   - ����ţ�    cmd   - �����루�������������б�����

    //       intr_addr() - Ӳ���жϴ��������н����õ�C��������ָ�롣

    // �ú�����Ӳ�̿���������֮��������ȫ��ָ�����do_hdΪӲ���жϴ��������н����õ�

    // C��������ָ�롣Ȼ���ٷ���Ӳ�̿����ֽں�7�ֽڵIJ�������顣

    // �ú�����Ӳ�̿���������֮��������ȫ�ֺ���ָ�����do_hdָ��Ӳ���жϴ��������н���

    // ���õ�C����������Ȼ���ٷ���Ӳ�̿����ֽں�7�ֽڵIJ�������顣Ӳ���жϴ�������Ĵ�

    // ��λ��kernel/sys_call.s�����235�д���

    // ��191�ж���1���Ĵ�������__res���ñ�������������1���Ĵ����У��Ա��ڿ��ٷ��ʡ�

    // �����ָ���Ĵ�������eax���������ǿ��԰Ѹþ�д�ɡ�register char __res asm("ax");����

187 static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,

188                 unsigned int head,unsigned int cyl,unsigned int cmd,

189                 void (*intr_addr)(void))

190 {

191         register int port asm("dx");    // ����ֲ��Ĵ�������������ָ���Ĵ���dx�С�

192

    // ���ȶԲ���������Ч�Լ�顣����������Ŵ���1��ֻ����0��1�����ߴ�ͷ�Ŵ���15�����

    // ��֧�֣�ͣ����������жϲ�ѭ���ȴ�����������������ȴ�һ��ʱ�����δ�������ʾ

    // Ӳ�̿�����������Ҳͣ����

193         if (drive>1 || head>15)

194                 panic("Trying to write bad sector");

195         if (!controller_ready())

196                 panic("HD controller not ready");

    // ������������Ӳ���жϷ���ʱ�����õ�C����ָ��do_hd���ú���ָ�붨����blk.h�ļ���

    // ��56--109��֮�䣬���ر��������еĵ�83�к�100�У���Ȼ������Ӳ�̿��������Ͳ���

    // ������֮ǰ���涨Ҫ�������������˿ڣ�0x3f6������һָ��Ӳ�̵Ŀ����ֽڣ��Խ�����

    // Ӧ��Ӳ�̿��Ʒ�ʽ���ÿ����ֽڼ���Ӳ����Ϣ�ṹ�����е� ctl �ֶΡ�Ȼ����������˿�

    // 0x1f1�C0x1f7����7�ֽڵIJ�������顣

197         SET_INTR(intr_addr);                    // do_hd = intr_addr���ж��б����á�

198         outb_p(hd_info[drive].ctl,HD_CMD);      // ����ƼĴ�����������ֽڡ�

199         port=HD_DATA;                           // ��dxΪ���ݼĴ����˿�(0x1f0)��

200         outb_p(hd_info[drive].wpcom>>2,++port); // ������дԤ���������(���4)��

201         outb_p(nsect,++port);                   // ��������/д����������

202         outb_p(sect,++port);                    // ��������ʼ������

203         outb_p(cyl,++port);                     // ����������ŵ�8λ��

204         outb_p(cyl>>8,++port);                  // ����������Ÿ�8λ��

205         outb_p(0xA0|(drive<<4)|head,++port);    // ��������������+��ͷ�š�

206         outb(cmd,++port);                       // ���Ӳ�̿������

207 }

208

    //// �ȴ�Ӳ�̾�����

    // �ú���ѭ���ȴ���״̬������æ��־λ��λ�������о�����Ѱ��������־��λ�����ʾӲ��

    // �������ɹ�����0��������һ��ʱ����Ϊæ���򷵻�1��

209 static int drive_busy(void)

210 {

211         unsigned int i;

212         unsigned char c;

213

    // ѭ����ȡ����������״̬�Ĵ���HD_STATUS���ȴ�������־λ��λ����æλ��λ��Ȼ����

    // ����æλ������λ��Ѱ������λ�������о�����Ѱ��������־��λ�����ʾӲ�̾���������

    // 0�������ʾ�ȴ���ʱ�����Ǿ�����ʾ��Ϣ��������1��

214         for (i = 0; i < 50000; i++) {

215                 c = inb_p(HD_STATUS);                     // ȡ��������״̬�ֽڡ�

216                 c &= (BUSY_STAT | READY_STAT | SEEK_STAT);

217                 if (c == (READY_STAT | SEEK_STAT))

218                         return 0;

219         }

220         printk("HD controller times out\n\r");   // �ȴ���ʱ����ʾ��Ϣ��������1��

221         return(1);

222 }

223

    //// ��ϸ�λ������У����Ӳ�̿�������

    // ��������ƼĴ����˿ڣ�0x3f6������������λ��4�������ֽڡ�Ȼ��ѭ���ղ����ȴ�һ��ʱ

    // ���ÿ�����ִ�и�λ��������������ö˿ڷ��������Ŀ����ֽ�(����ֹ���ԡ��ض�)������

    // ��Ӳ�̾��������ȴ�Ӳ�̾�����ʱ������ʾ������Ϣ��Ȼ���ȡ����Ĵ������ݣ����䲻��

    // ��1����ʾ�޴�������ʾӲ�̿�������λʧ����Ϣ��

224 static void reset_controller(void)

225 {

226         int     i;

227

228         outb(4,HD_CMD);                       // ����ƼĴ����˿ڷ��͸�λ�����ֽڡ�

229         for(i = 0; i < 1000; i++) nop();      // �ȴ�һ��ʱ�䡣

230         outb(hd_info[0].ctl & 0x0f ,HD_CMD);  // �������������ֽ�(����ֹ���ԡ��ض�)��

231         if (drive_busy())

232                 printk("HD-controller still busy\n\r");

233         if ((i = inb(HD_ERROR)) != 1)

234                 printk("HD-controller reset failed: %02x\n\r",i);

235 }

236

    //// Ӳ�̸�λ������

    // ���ȸ�λ������У����Ӳ�̿�������Ȼ����Ӳ�̿���������������������������ڱ�

    // ���������Ӳ���жϴ����������ֻ���ñ���������ʱ�ú��������ִ�и�����Ľ����

    // ���Ƿ�Ҫ���г����������Ǽ���ִ���������������

237 static void reset_hd(void)

238 {

239         static int i;

240

    // �����λ��־reset����λ�ģ����ڰѸ�λ��־�����ִ�и�λӲ�̿�����������Ȼ��

    // ��Ե�i��Ӳ������������͡����������������������������ִ���˸�������ֻ�

    // ����Ӳ���ж��źš���ʱ�������ᱻ�жϹ��̵��ö��ٴ�ִ�С�����reset�Ѿ���־��λ��

    // ��˻�����ȥִ��246�п�ʼ����䣬�ж�����ִ���Ƿ������������Ƿ�������ͻ����

    // bad_rw_intr() ������ͳ�Ƴ������������ݴ�ȷ���Ƿ�������reset��־�������������

    // reset��־����ת��repeat����ִ�б�����������λ�����������������һ��Ӳ�̷���

    // �����������������������������ͬ�����������ϵͳ��NR_HD��Ӳ�̶��Ѿ�����ִ��

    // �˷��͵�������ٴ�do_hd_request()������ʼ����������д�����

241 repeat:

242         if (reset) {

243                 reset = 0;

244                 i = -1;                       // ��ʼ����ǰӲ�̺ţ���̬��������

245                 reset_controller();

246         } else if (win_result()) {

247                 bad_rw_intr();

248                 if (reset)

249                         goto repeat;

250         }

251         i++;                                  // ������һ��Ӳ�̣���1����0����

252         if (i < NR_HD) {

253                 hd_out(i,hd_info[i].sect,hd_info[i].sect,hd_info[i].head-1,

254                         hd_info[i].cyl,WIN_SPECIFY,&reset_hd);

255         } else

256                 do_hd_request();              // ִ�����������

257 }

258

    //// ����Ӳ���жϵ��ú�����

    // ��������Ӳ���ж�ʱ��Ӳ���жϴ��������е��õ�Ĭ��C�����������ڱ����ú���ָ��Ϊ

    // NULLʱ���øú������μ���kernel/sys_call.s����256�У����ú�������ʾ������Ϣ��

    // ���ø�λ��־reset��Ȼ����������������go_hd_request()��������ִ�и�λ����

    // ������

259 void unexpected_hd_interrupt(void)

260 {

261         printk("Unexpected HD interrupt\n\r");

262         reset = 1;

263         do_hd_request();

264 }

265

    //// ��дӲ��ʧ�ܴ������ú�����

    // ���������ʱ�ij����������ڻ����7��ʱ���������ǰ��������ѵȴ�������Ľ��̣�

    // ���Ҷ�Ӧ���������±�־��λ����ʾ����û�и��¡������дһ����ʱ�ij��������Ѿ�����

    // 3�Σ���Ҫ��ִ�и�λӲ�̿��������������ø�λ��־����

266 static void bad_rw_intr(void)

267 {

268         if (++CURRENT->errors >= MAX_ERRORS)

269                 end_request(0);

270         if (CURRENT->errors > MAX_ERRORS/2)

271                 reset = 1;

272 }

273

    //// �������жϵ��ú�����

    // �ú�������Ӳ�̶��������ʱ������Ӳ���жϹ����б����á�

    // �ڶ�����ִ�к�����Ӳ���ж��źţ���ִ��Ӳ���жϴ������򣬴�ʱ��Ӳ���жϴ�������

    // �е��õ�C����ָ��do_hd�Ѿ�ָ��read_intr()����˻���һ�ζ�����������ɣ��������

    // ��ͻ�ִ�иú�����

274 static void read_intr(void)

275 {

    // �ú��������жϴ˴ζ���������Ƿ����������������������������æ״̬����������

    // ִ�д�������Ӳ�̲���ʧ�����⣬�����ٴ�����Ӳ������λ������ִ�����������

    // Ȼ�󷵻ء�ÿ�ζ�������������Ե�ǰ�����������������ۼƣ����������������������

    // ����������һ�룬�����ִ��Ӳ�̸�λ������Ȼ����ִ�б������������������������

    // �����ڵ������������������MAX_ERRORS��7�Σ������������������Ĵ�����ȥ������

    // ������һ�������

276         if (win_result()) {                   // ��������æ����д��������ִ�д���

277                 bad_rw_intr();                // ����ж�дӲ��ʧ�ܴ�����

278                 do_hd_request();              // �ٴ�����Ӳ������Ӧ(��λ)������

279                 return;

280         }

    // ���������û�г�����������ݼĴ����˿ڰ�1�����������ݶ���������Ļ������У�����

    // �ݼ������������ȡ��������ֵ�����ݼ��󲻵��� 0����ʾ��������������ûȡ�꣬����

    // �ٴ����жϵ���C����ָ��do_hdΪread_intr()��ֱ�ӷ��أ��ȴ�Ӳ���ڶ�����1������

    // ���ݺ󷢳��жϲ��ٴε��ñ�������ע�⣺281������е�256��ָ�ڴ��֣���512�ֽڡ�

    // ע��1��262���ٴ���do_hdָ��ָ��read_intr()����ΪӲ���жϴ�������ÿ�ε���do_hd

    // ʱ���Ὣ�ú���ָ���ÿա��μ�sys_call.s�����251��253�С�

281         port_read(HD_DATA,CURRENT->buffer,256);    // �����ݵ�����ṹ��������

282         CURRENT->errors = 0;                 // �����������

283         CURRENT->buffer += 512;              // ����������ָ�룬ָ���µĿ�����

284         CURRENT->sector++;                   // ��ʼ�����ż�1��

285         if (--CURRENT->nr_sectors) {         // ��������������������û���꣬����

286                 SET_INTR(&read_intr);        // ��Ӳ�̵���C����ָ��Ϊread_intr()��

287                 return;

288         }

    // ִ�е��ˣ�˵�������������ȫ�����������Ѿ����꣬�����end_request()����ȥ������

    // ����������ˡ� ����ٴε��� do_hd_request()��ȥ��������Ӳ�������ִ������Ӳ��

    // ���������

289         end_request(1);                         // �����Ѹ��±�־��λ��1����

290         do_hd_request();

291 }

292

    //// д�����жϵ��ú�����

    // �ú�������Ӳ��д�������ʱ������Ӳ���жϹ����б����á�����������read_intr()���ơ�

    // ��д����ִ�к�����Ӳ���ж��źţ���ִ��Ӳ���жϴ������򣬴�ʱ��Ӳ���жϴ�������

    // �е��õ�C����ָ��do_hd�Ѿ�ָ��write_intr()����˻���һ��д����������ɣ��������

    // ��ͻ�ִ�иú�����

293 static void write_intr(void)

294 {

    // �ú��������жϴ˴�д��������Ƿ����������������������������æ״̬����������

    // ִ�д�������Ӳ�̲���ʧ�����⣬�����ٴ�����Ӳ������λ������ִ�����������

    // Ȼ�󷵻ء��� bad_rw_intr() �����У�ÿ�β�����������Ե�ǰ�����������������ۼƣ�

    // �������������������������������һ�룬�����ִ��Ӳ�̸�λ������Ȼ����ִ�б�����

    // ������������������Ѿ����ڵ������������������MAX_ERRORS��7�Σ������������

    // ������Ĵ�����ȥ������������һ�������do_hd_request()�л���ݵ�ʱ����ı�־

    // ״̬���б��Ƿ���Ҫ��ִ�и�λ������У���Ȳ�����Ȼ���ټ���������һ�������

295         if (win_result()) {                 // ���Ӳ�̿��������ش�����Ϣ��

296                 bad_rw_intr();              // �����Ƚ���Ӳ�̶�дʧ�ܴ�����

297                 do_hd_request();            // �ٴ�����Ӳ������Ӧ(��λ)������

298                 return;

299         }

    // ��ʱ˵������дһ���������ɹ�����˽���д��������1�����䲻Ϊ0����˵����������

    // Ҫд�����ǰѵ�ǰ������ʼ������ +1�����������������ݻ�����ָ��ָ����һ����д��

    // ���ݡ�Ȼ��������Ӳ���жϴ��������е��õ�C����ָ��do_hd��ָ�򱾺�������������

    // ���������ݶ˿�д��512�ֽ����ݣ�Ȼ��������ȥ�ȴ�����������Щ����д��Ӳ�̺��

    // �����жϡ�

300         if (--CURRENT->nr_sectors) {          // ����������Ҫд����

301                 CURRENT->sector++;            // ��ǰ������ʼ������+1��

302                 CURRENT->buffer += 512;       // �������󻺳���ָ�룬

303                 SET_INTR(&write_intr);        // do_hd�ú���ָ��Ϊwrite_intr()��

304                 port_write(HD_DATA,CURRENT->buffer,256);  // �����ݶ˿�д256�֡�

305                 return;

306         }

    // �������������ȫ�����������Ѿ�д�꣬�����end_request()����ȥ����������������ˡ�

    // ����ٴε��� do_hd_request()��ȥ��������Ӳ�������ִ������Ӳ�����������

307         end_request(1);                       // ��������������ˣ������ø��±�־����

308         do_hd_request();                      // ִ������Ӳ�����������

309 }

310

    //// Ӳ������У������λ���жϵ��ú�����

    // �ú�������Ӳ��ִ������У��������������Ӳ���ж��б����á�

    // ���Ӳ�̿��������ش�����Ϣ���������Ƚ���Ӳ�̶�дʧ�ܴ�����Ȼ������Ӳ������Ӧ

    // ����λ�������� �� bad_rw_intr() �����У�ÿ�β�����������Ե�ǰ����������������

    // �ۼƣ��������������������������������һ�룬�����ִ��Ӳ�̸�λ������Ȼ����ִ��

    // ������������������������Ѿ����ڵ������������������MAX_ERRORS��7�Σ������

    // ������������Ĵ�����ȥ������������һ�������do_hd_request() �л���ݵ�ʱ����

    // �ı�־״̬���б��Ƿ���Ҫ��ִ�и�λ������У���Ȳ�����Ȼ���ټ���������һ�����

311 static void recal_intr(void)

312 {

313         if (win_result())                // �����س����������bad_rw_intr()��

314                 bad_rw_intr();

315         do_hd_request();

316 }

317

    // Ӳ�̲�����ʱ������

    // ����������do_timer()�У�kernel/sched.c����340�У������á�����Ӳ�̿�����������

    // һ����������ھ�����hd_timeout��ϵͳ�δ���������û�з���һ��Ӳ���ж��źţ�

    // ��˵������������Ӳ�̣�������ʱ����ʱdo_timer()�ͻ���ñ��������ø�λ��־reset

    // ������do_hd_request()ִ�и�λ����������Ԥ��ʱ���ڣ�200�δ�Ӳ�̿�����������Ӳ

    // ���жϲ���ʼִ��Ӳ���жϴ���������ôht_timeoutֵ�ͻ����жϴ��������б���0��

    // ��ʱdo_timer()�ͻ�������������

318 void hd_times_out(void)

319 {

    // �����ǰ��û��������Ҫ�������豸������ָ��ΪNULL�������޳�ʱ���ԣ�ֱ�ӷ��ء���

    // ������ʾ������Ϣ��Ȼ���жϵ�ǰ������ִ�й����з����ij��������Ƿ��Ѿ������趨ֵ

    // MAX_ERRORS��7�������������ʧ����ʽ��������������Ĵ��������������ݸ��±�־����

    // Ȼ����жϹ����е��õ�C����ָ��do_hd�ÿգ������ø�λ��־reset���̶���������

    // ��������do_hd_request()��ȥִ�и�λ������

320         if (!CURRENT)

321                 return;

322         printk("HD timeout");

323         if (++CURRENT->errors >= MAX_ERRORS)

324                 end_request(0);

325         SET_INTR(NULL);                        // ��do_hd = NULL,time_out=200��

326         reset = 1;                             // ���ø�λ��־��

327         do_hd_request();

328 }

329

    //// ִ��Ӳ�̶�д���������

    // �ú��������豸��ǰ�������е��豸�ź���ʼ��������Ϣ���ȼ���õ���ӦӲ���ϵ�����š�

    // ��ǰ�ŵ��������š���ͷ�����ݣ�Ȼ���ٸ����������е����READ/WRITE����Ӳ�̷�����Ӧ

    // ��/д��� ����������λ��־��Ӳ������У����־�ѱ���λ����ô���Ȼ�ȥִ�и�λ������

    // У��������

    // ���������ʱ�ǿ��豸�ĵ�1����ԭ���豸���У�������豸��ǰ������ָ���ֱ��ָ�����

    // ����μ�ll_rw_blk.c��28�У����������̵��ñ�����ִ�ж�д������������һ����д����

    // ��ɶ�������Ӳ���жϹ����У���������������Ҫ��������Ҳ����Ӳ���жϹ����е��ñ�������

    // �μ�kernel/sys_call.s��235�С�

330 void do_hd_request(void)

331 {

332         int i,r;

333         unsigned int block,dev;

334         unsigned int sec,head,cyl;

335         unsigned int nsect;

336

    // �������ȼ��������ĺϷ��ԡ��������������û�����������˳����μ�blk.h��127�У���

    // Ȼ��ȡ�豸���е����豸�ţ����б����Ӳ���豸�ŵ�˵�����Լ��豸��ǰ�������е���ʼ

    // �����š����豸�ż���ӦӲ���ϸ�������������豸�Ų����ڻ�����ʼ�������ڸ� ������

    // ����-2������������������ת�����repeat����������INIT_REQUEST��ʼ��������Ϊ

    // һ��Ҫ���дһ�����ݣ�2����������1024�ֽڣ�����������������Ų��ܴ��ڷ��������

    // �����ڶ��������š�Ȼ��ͨ���������豸�Ŷ�Ӧ��������ʼ�����ţ��Ͱ���Ҫ��д�Ŀ��Ӧ

    // ������Ӳ�̵ľ���������block�ϡ������豸�ű�5�������ɵõ���Ӧ��Ӳ�̺š�

337         INIT_REQUEST;

338         dev = MINOR(CURRENT->dev);

339         block = CURRENT->sector;                         // �������ʼ������

340         if (dev >= 5*NR_HD || block+2 > hd[dev].nr_sects) {

341                 end_request(0);

342                 goto repeat;                             // �ñ����blk.h����档

343         }

344         block += hd[dev].start_sect;

345         dev /= 5;                      // ��ʱdev����Ӳ�̺ţ�Ӳ��0����Ӳ��1����

    // Ȼ�������õľ���������block��Ӳ�̺�dev�����ǾͿ��Լ������ӦӲ���еĴŵ�����

    // ���ţ�sec������������ţ�cyl�� �ʹ�ͷ�ţ�head���� ����Ƕ��Ļ����뼴��������Ӳ

    // ����Ϣ�ṹ�е�ÿ�ŵ���������Ӳ�̴�ͷ����������Щ���ݡ����㷽��Ϊ��

    // 310--311�д����ʼʱeax��������block��edx����0��divlָ���edx:eax��ɵ�����

    // �ų���ÿ�ŵ���������hd_info[dev].sect��������������ֵ��eax�У�������edx�С���

    // ��eax���ǵ�ָ��λ�õĶ�Ӧ�ܴŵ��������д�ͷ�棩��edx���ǵ�ǰ�ŵ��ϵ������š�

    // 312--313�д����ʼʱeax�Ǽ�����Ķ�Ӧ�ܴŵ�����edx����0��divlָ���edx:eax

    // �Ķ�Ӧ�ܴŵ�������Ӳ���ܴ�ͷ����hd_info[dev].head������eax�еõ�������ֵ������

    // �ţ�cyl����edx�еõ����������Ƕ�Ӧ�õ�ǰ��ͷ�ţ�head����

346         __asm__("divl %4":"=a" (block),"=d" (sec):"0" (block),"1" (0),

347                 "r" (hd_info[dev].sect));

348         __asm__("divl %4":"=a" (cyl),"=d" (head):"0" (block),"1" (0),

349                 "r" (hd_info[dev].head));

350         sec++;                               // �Լ������õ�ǰ�ŵ������Ž��е�����

351         nsect = CURRENT->nr_sectors;         // ����/д����������

    // ��ʱ���ǵõ�������д��Ӳ����ʼ����block����Ӧ��Ӳ��������ţ�cyl�����ڵ�ǰ�ŵ�

    // �ϵ������ţ�sec������ͷ�ţ�head���Լ�����д������������nsect���� �������ǿ��Ը�

    // ����Щ��Ϣ��Ӳ�̿���������I/O������Ϣ�ˡ� ���ڷ���֮ǰ���ǻ���Ҫ�ȿ����Ƿ��и�

    // λ������״̬������У��Ӳ�̵ı�־��ͨ���ڸ�λ����֮����Ҫ����У��Ӳ�̴�ͷλ�á�

    // ����Щ��־�ѱ���λ����˵��ǰ���Ӳ�̲������ܳ�����һЩ���⣬����������ϵͳ��һ

    // ��Ӳ�̶�д����������� �������Ǿ���Ҫ���¸�λӲ�̻������������У��Ӳ�̡�

 

    // �����ʱ��λ��־reset����λ�ģ�����Ҫִ�и�λ��������λӲ�̺Ϳ�����������Ӳ��

    // ��Ҫ����У����־�����ء�reset_hd()��������Ӳ�̿��������͸�λ������У�������

    // Ȼ����Ӳ�̿��������������������������

352         if (reset) {

353                 recalibrate = 1;             // ��������У����־��

354                 reset_hd();

355                 return;

356         }

    // �����ʱ����У����־��recalibrate������λ�ģ������ȸ�λ�ñ�־��Ȼ����Ӳ�̿���

    // ����������У������������ִ��Ѱ���������ô����κεط��Ĵ�ͷ�ƶ���0���档

357         if (recalibrate) {

358                 recalibrate = 0;

359                 hd_out(dev,hd_info[CURRENT_DEV].sect,0,0,0,

360                         WIN_RESTORE,&recal_intr);

361                 return;

362         }      

    // �������������־��û����λ����ô���ǾͿ��Կ�ʼ��Ӳ�̿������������������ݶ�/д

    // ���������ˡ������ǰ������д��������������д���ѭ����ȡ״̬�Ĵ�����Ϣ����

    // ����������־DRQ_STAT�Ƿ���λ��DRQ_STAT��Ӳ��״̬�Ĵ������������λ����ʾ��

    // �����Ѿ�׼���������������ݶ˿�֮�䴫��һ���ֻ�һ���ֽڵ����ݡ��ⷽ�����Ϣ�ɲ�

    // ������ǰ���Ӳ�̲�����/дʱ��ͼ������������DRQ��λ���˳�ѭ���� ���ȵ�ѭ����

    // ��Ҳû����λ�����ʾ���͵�Ҫ��дӲ������ʧ�ܣ�������תȥ�������ֵ���������ִ

    // ����һ��Ӳ�����󡣷������ǾͿ�����Ӳ�̿��������ݼĴ����˿�HD_DATAд��1������

    // �����ݡ�

363         if (CURRENT->cmd == WRITE) {

364                 hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);

365                 for(i=0 ; i<10000 && !(r=inb_p(HD_STATUS)&DRQ_STAT) ; i++)

366                         /* nothing */ ;

367                 if (!r) {

368                         bad_rw_intr();

369                         goto repeat;                // �ñ����blk.h�ļ�����档

370                 }

371                 port_write(HD_DATA,CURRENT->buffer,256);

    // �����ǰ�����Ƕ�Ӳ�����ݣ�����Ӳ�̿��������Ͷ����������������Ч��ͣ����

372         } else if (CURRENT->cmd == READ) {

373                 hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr);

374         } else

375                 panic("unknown hd-command");

376 }

377

    // Ӳ��ϵͳ��ʼ����

    // ����Ӳ���ж���������������Ӳ�̿����������ж������źš�

    // �ú�������Ӳ���豸�������������ָ��Ϊdo_hd_request()��Ȼ������Ӳ���ж�������

    // ����hd_interrupt��kernel/sys_call.s����235�У������жϴ������̵�ַ�� Ӳ���жϺ�

    // Ϊint 0x2E��46������Ӧ8259AоƬ���ж������ź�IRQ13�����Ÿ�λ��������8259A int2

    // ������λ��������Ƭ�����ж������źš��ٸ�λӲ�̵��ж���������λ���ڴ�Ƭ�ϣ�������

    // Ӳ�̿����������ж������źš��ж���������IDT���ж������������ú�set_intr_gate()

    // ��include/asm/system.h��ʵ�֡�

378 void hd_init(void)

379 {

380         blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;     // do_hd_request()��

381         set_intr_gate(0x2E,&hd_interrupt);  // �����ж����д�������ָ�롣

382         outb_p(inb_p(0x21)&0xfb,0x21);      // ��λ��������8259A int2������λ��

383         outb(inb_p(0xA1)&0xbf,0xA1);        // ��λӲ���ж���������λ���ڴ�Ƭ�ϣ���

384 }

385