����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