����9-5 linux/kernel/blk_drv/floppy.c


  1 /*

  2  *  linux/kernel/floppy.c

  3  *

  4  *  (C) 1991  Linus Torvalds

  5  */

  6

  7 /*

  8  * 02.12.91 - Changed to static variables to indicate need for reset

  9  * and recalibrate. This makes some things easier (output_byte reset

 10  * checking etc), and means less interrupt jumping in case of errors,

 11  * so the code is hopefully easier to understand.

 12  */

    /*

     * 02.12.91 - �޸ijɾ�̬����������Ӧ��λ������У����������ʹ��ijЩ����

     * ��������Ϊ���㣨output_byte ��λ���ȣ���������ζ���ڳ���ʱ�ж���ת

     * Ҫ��һЩ������Ҳϣ�������ܸ����ױ����⡣

     */

 13

 14 /*

 15  * This file is certainly a mess. I've tried my best to get it working,

 16  * but I don't like programming floppies, and I have only one anyway.

 17  * Urgel. I should check for more errors, and do more graceful error

 18  * recovery. Seems there are problems with several drives. I've tried to

 19  * correct them. No promises.

 20  */

    /*

     * ����ļ���Ȼ�Ƚϻ��ҡ����Ѿ���������ʹ���ܹ����������Ҳ�ϲ��������̣�

     * ������Ҳֻ��һ�����������⣬��Ӧ��������IJ���������Լ���������Ĵ���

     * ����ijЩ��������������������󻹴���һЩ���⡣���Ѿ������Ž��о����ˣ�

     * �����ܱ�֤��������ʧ��

     */

 21

 22 /*

 23  * As with hd.c, all routines within this file can (and will) be called

 24  * by interrupts, so extreme caution is needed. A hardware interrupt

 25  * handler may not sleep, or a kernel panic will happen. Thus I cannot

 26  * call "floppy-on" directly, but have to set a special timer interrupt

 27  * etc.

 28  *

 29  * Also, I'm not certain this works on more than 1 floppy. Bugs may

 30  * abund.

 31  */

    /*

     * ��ͬhd.c�ļ�һ�������ļ��е������ӳ����ܹ����жϵ��ã�������Ҫ�ر�

     * ��С�ġ�Ӳ���жϴ��������Dz���˯�ߵģ������ں˾ͻ�ɵ��(����)J����˲���

     * ֱ�ӵ���"floppy-on"����ֻ������һ������Ķ�ʱ�жϵȡ�

     *

     * ���⣬�Ҳ��ܱ�֤�ó������ڶ���1��������ϵͳ�Ϲ������п��ܴ��ڴ���

     */

 32

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

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

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

 36 #include <linux/fdreg.h>  // ����ͷ�ļ����������̿�����������һЩ���塣

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

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

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

 40

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

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

 41 #define MAJOR_NR 2        // ���������豸����2��

 42 #include "blk.h"          // ���豸ͷ�ļ�����������ṹ�����豸�ṹ�ͺ꺯������Ϣ��

 43

 44 static int recalibrate = 0;        // ��־��1��ʾ��Ҫ����У����ͷλ�ã���ͷ���������

 45 static int reset = 0;              // ��־��1��ʾ��Ҫ���и�λ������

 46 static int seek = 0;               // ��־��1��ʾ��Ҫִ��Ѱ��������

 47

    // ��ǰ��������Ĵ���DOR��Digital Output Register����������kernel/sched.c��223�С�

    // �ñ����������������е���Ҫ��־������ѡ�����������Ƶ��������������λ���̿�������

    // ������/��ֹDMA���ж�������μ������б����DOR�Ĵ�����˵����

 48 extern unsigned char current_DOR;

 49

    // �ֽ�ֱ���������Ƕ����꣩����ֵval�����port�˿ڡ�

 50 #define immoutb_p(val,port) \

 51 __asm__("outb %0,%1\n\tjmp 1f\n1:\tjmp 1f\n1:"::"a" ((char) (val)),"i" (port))

 52

    // �������궨�����ڼ����������豸�š�

    // ����x�Ǵ��豸�š����豸�� = TYPE*4 + DRIVE�����㷽���μ��б���

 53 #define TYPE(x) ((x)>>2)           // �������ͣ�2--1.2Mb��7--1.44Mb����

 54 #define DRIVE(x) ((x)&0x03)        // ������ţ�0--3��ӦA--D����

 55 /*

 56  * Note that MAX_ERRORS=8 doesn't imply that we retry every bad read

 57  * max 8 times - some types of errors increase the errorcount by 2,

 58  * so we might actually retry only 5-6 times before giving up.

 59  */

    /*

     * ע�⣬���涨��MAX_ERRORS=8������ʾ��ÿ�ζ����������8�� - ��Щ����

     * �Ĵ����ѳ�������ֵ��2����������ʵ�����ڷ�������֮ǰֻ�賢��5-6�鼴�ɡ�

     */

 60 #define MAX_ERRORS 8

 61

 62 /*

 63  * globals used by 'result()'

 64  */

    /* �����Ǻ���'result()'ʹ�õ�ȫ�ֱ��� */

    // ��Щ״̬�ֽ��и�����λ�ĺ�����μ�include/linux/fdreg.hͷ�ļ������μ��б���˵����

 65 #define MAX_REPLIES 7                            // FDC��෵��7�ֽڵĽ����Ϣ��

 66 static unsigned char reply_buffer[MAX_REPLIES];  // ���FDC���ص�Ӧ������Ϣ��

 67 #define ST0 (reply_buffer[0])                    // ���״̬�ֽ�0��

 68 #define ST1 (reply_buffer[1])                    // ���״̬�ֽ�1��

 69 #define ST2 (reply_buffer[2])                    // ���״̬�ֽ�2��

 70 #define ST3 (reply_buffer[3])                    // ���״̬�ֽ�3��

 71

 72 /*

 73  * This struct defines the different floppy types. Unlike minix

 74  * linux doesn't have a "search for right type"-type, as the code

 75  * for that is convoluted and weird. I've got enough problems with

 76  * this driver as it is.

 77  *

 78  * The 'stretch' tells if the tracks need to be boubled for some

 79  * types (ie 360kB diskette in 1.2MB drive etc). Others should

 80  * be self-explanatory.

 81  */

    /*

     * ��������̽ṹ�����˲�ͬ���������͡���minix��ͬ���ǣ�Linuxû��

     * "������ȷ������"-���ͣ���Ϊ���䴦���Ĵ������˷ѽ��ҹֵֹġ�������

     * �Ѿ���������̫��������ˡ�

     *

     * ��ijЩ���͵����̣�������1.2MB�������е�360kB���̵ȣ���'stretch'

     * ���ڼ��ŵ��Ƿ���Ҫ���⴦������������Ӧ���������ġ�

     */

    // �������̽ṹ�����̲����У�

    // size          ��С(������)��

    // sect          ÿ�ŵ���������

    // head          ��ͷ����

    // track         �ŵ�����

    // stretch       �Դŵ��Ƿ�Ҫ���⴦������־����

    // gap           ������϶����(�ֽ���)��

    // rate          ���ݴ������ʣ�

    // spec1         ��������4λ�������ʣ�����λ��ͷж��ʱ�䣩��

 82 static struct floppy_struct {

 83         unsigned int size, sect, head, track, stretch;

 84         unsigned char gap,rate,spec1;

 85 } floppy_type[] = {

 86         {    0, 0,0, 0,0,0x00,0x00,0x00 },      /* no testing */

 87         {  720, 9,2,40,0,0x2A,0x02,0xDF },      /* 360kB PC diskettes */

 88         { 2400,15,2,80,0,0x1B,0x00,0xDF },      /* 1.2 MB AT-diskettes */

 89         {  720, 9,2,40,1,0x2A,0x02,0xDF },      /* 360kB in 720kB drive */

 90         { 1440, 9,2,80,0,0x2A,0x02,0xDF },      /* 3.5" 720kB diskette */

 91         {  720, 9,2,40,1,0x23,0x01,0xDF },      /* 360kB in 1.2MB drive */

 92         { 1440, 9,2,80,0,0x23,0x01,0xDF },      /* 720kB in 1.2MB drive */

 93         { 2880,18,2,80,0,0x1B,0x00,0xCF },      /* 1.44MB diskette */

 94 };

 95

 96 /*

 97  * Rate is 0 for 500kb/s, 2 for 300kbps, 1 for 250kbps

 98  * Spec1 is 0xSH, where S is stepping rate (F=1ms, E=2ms, D=3ms etc),

 99  * H is head unload time (1=16ms, 2=32ms, etc)

100  *

101  * Spec2 is (HLD<<1 | ND), where HLD is head load time (1=2ms, 2=4 ms etc)

102  * and ND is set means no DMA. Hardcoded to 6 (HLD=6ms, use DMA).

103  */

    /*

     * ��������rate��0��ʾ500kbps��1��ʾ300kbps��2��ʾ250kbps��

     * ����spec1��0xSH������S�Dz������ʣ�F-1ms��E-2ms��D=3ms�ȣ���

     * H�Ǵ�ͷж��ʱ�䣨1=16ms��2=32ms�ȣ�

     *

     * spec2�ǣ�HLD<<1 | ND��������HLD�Ǵ�ͷ����ʱ�䣨1=2ms��2=4ms�ȣ�

     * ND��λ��ʾ��ʹ��DMA��No DMA�����ڳ�����Ӳ�����6��HLD=6ms��ʹ��DMA����

     */

    // ע�⣬������ͷ����ʱ�����дHLD���д�ɱ�׼��HLT��Head Load Time����

104

    // floppy_interrupt()��sys_call.s�����������жϴ������̱�š����ォ�����̳�ʼ��

    // ����floppy_init()����469�У�ʹ������ʼ���ж���������������

105 extern void floppy_interrupt(void);

    // ����boot/head.s��132�д��������ʱ���̻����������������Ļ����������ڴ�1MB

    // ����ij���ط�������Ҫ��DMA������������ʱ�������򴦡���Ϊ8237AоƬֻ����1MB��

    // ַ��Χ��Ѱַ��

106 extern char tmp_floppy_area[1024];

107

108 /*

109  * These are global variables, as that's the easiest way to give

110  * information to interrupts. They are the data used for the current

111  * request.

112  */

    /*

     * ������һЩȫ�ֱ�������Ϊ���ǽ���Ϣ�����жϳ�����򵥵ķ�ʽ������

     * ���ڵ�ǰ����������ݡ�

     */

    // ��Щ��ν�ġ�ȫ�ֱ�������ָ�������жϴ��������е��õ�C����ʹ�õı�������Ȼ��Щ

    // C�������ڱ������ڡ�

113 static int cur_spec1 = -1;                           // ��ǰ���̲���spec1��

114 static int cur_rate = -1;                            // ��ǰ����ת��rate��

115 static struct floppy_struct * floppy = floppy_type;  // �������ͽṹ����ָ�롣

116 static unsigned char current_drive = 0;              // ��ǰ�������š�

117 static unsigned char sector = 0;                     // ��ǰ�����š�

118 static unsigned char head = 0;                       // ��ǰ��ͷ�š�

119 static unsigned char track = 0;                      // ��ǰ�ŵ��š�

120 static unsigned char seek_track = 0;                 // Ѱ���ŵ��š�

121 static unsigned char current_track = 255;            // ��ǰ��ͷ���ڴŵ��š�

122 static unsigned char command = 0;                    // ��/д���

123 unsigned char selected = 0;    // ������ѡ����־���ڴ���������֮ǰҪ����ѡ��������

124 struct task_struct * wait_on_floppy_select = NULL;   // �ȴ�ѡ��������������С�

125

    //// ȡ��ѡ��������

    // �����������ָ��������nr��ǰ��û�б�ѡ��������ʾ������Ϣ��Ȼ��λ������ѡ����־

    // selected�������ѵȴ�ѡ���������������������Ĵ���(DOR)�ĵ�2λ����ָ��ѡ�����

    // ����0-3��ӦA-D����

126 void floppy_deselect(unsigned int nr)

127 {

128         if (nr != (current_DOR & 3))

129                 printk("floppy_deselect: drive not selected\n\r");

130         selected = 0;                                // ��λ������ѡ����־��

131         wake_up(&wait_on_floppy_select);             // ���ѵȴ�������

132 }

133

134 /*

135  * floppy-change is never called from an interrupt, so we can relax a bit

136  * here, sleep etc. Note that floppy-on tries to set current_DOR to point

137  * to the desired drive, but it will probably not survive the sleep if

138  * several floppies are used at the same time: thus the loop.

139  */

    /*

     * floppy-change()���Ǵ��жϳ����е��õģ������������ǿ�������һ�£�˯�ߵȡ�

     * ע��floppy-on()�᳢������current_DORָ�������������������ͬʱʹ�ü���

     * ����ʱ����˯�ߣ���˴�ʱֻ��ʹ��ѭ����ʽ��

     */

    //// ���ָ�����������̸��������

    // ����nr�������š�������̸������򷵻�1�����򷵻�0��

    // �ú�������ѡ������ָ��������nr��Ȼ��������̿���������������Ĵ���DIR��ֵ������

    // ���������е������Ƿ񱻸��������ú����ɳ���fs/buffer.c�е� check_disk_change()��

    // �����ã���119�У���

140 int floppy_change(unsigned int nr)

141 {

    // ����Ҫ��������������ת�������ﵽ��������ת�١�����Ҫ����һ��ʱ�䡣���õķ�������

    // ��kernel/sched.c�����̶�ʱ����do_floppy_timer()����һ������ʱ������floppy_on()

    // �����������ж���ʱ�Ƿ񵽣�mon_timer[nr]==0?������û�е����õ�ǰ���̼���˯�ߵȴ���

    // ����ʱ����do_floppy_timer()�ỽ�ѵ�ǰ���̡�

142 repeat:

143         floppy_on(nr);        // �������ȴ�ָ������nr��kernel/sched.c����251�У���

    // ��������������ת��֮���������鿴һ�µ�ǰѡ��������Dz��Ǻ�������ָ��������nr��

    // �����ǰѡ�����������ָ��������nr�������Ѿ�ѡ�����������������õ�ǰ��������

    // �жϵȴ�״̬���Եȴ�����������ȡ��ѡ�����μ�����floppy_deselect()�� �����ǰû

    // ��ѡ������������������������ȡ��ѡ����ʹ��ǰ���񱻻���ʱ�� ��ǰ������Ȼ����ָ��

    // ������nr������ת��������ʼ������ѭ���ȴ���

144         while ((current_DOR & 3) != nr && selected)

145                 sleep_on(&wait_on_floppy_select);

146         if ((current_DOR & 3) != nr)

147                 goto repeat;

    // �������̿�������ѡ������ָ��������nr������ȡ��������Ĵ���DIR��ֵ����������

    // λ��λ7����λ�����ʾ�����Ѹ�������ʱ���ɹر����ﲢ����1�˳��� ����ر����ﷵ

    // ��0�˳�����ʾ����û�б�������

148         if (inb(FD_DIR) & 0x80) {

149                 floppy_off(nr);

150                 return 1;

151         }

152         floppy_off(nr);

153         return 0;

154 }

155

    //// �����ڴ滺��飬��1024�ֽڡ�

    // ���ڴ��ַfrom������1024�ֽ����ݵ���ַto����

156 #define copy_buffer(from,to) \

157 __asm__("cld ; rep ; movsl" \

158         ::"c" (BLOCK_SIZE/4),"S" ((long)(from)),"D" ((long)(to)) \

159         :"cx","di","si")

160

    //// ���ã���ʼ��������DMAͨ����

    // ���������ݶ�д������ʹ��DMA���еġ������ÿ�ν������ݴ���֮ǰ��Ҫ����DMAоƬ

    // ��ר������������ͨ��2���й�DMA��̷�����μ������б������Ϣ��

161 static void setup_DMA(void)

162 {

163         long addr = (long) CURRENT->buffer;      // ��ǰ��������������ڴ��ַ��

164

    // ���ȼ��������Ļ���������λ�á���������������ڴ�1MB���ϵ�ij���ط�������Ҫ��

    // DMA������������ʱ��������tmp_floppy_area��������Ϊ8237AоƬֻ����1MB��ַ��

    // Χ��Ѱַ�������д���������Ҫ�����ݴ�������������Ƶ�����ʱ����

165         cli();

166         if (addr >= 0x100000) {

167                 addr = (long) tmp_floppy_area;

168                 if (command == FD_WRITE)

169                         copy_buffer(CURRENT->buffer,tmp_floppy_area);

170         }

    // ���������ǿ�ʼ����DMAͨ��2���ڿ�ʼ����֮ǰ��Ҫ�����θ�ͨ������ͨ�����μĴ���

    // �˿�Ϊ0x0A��λ0-1ָ��DMAͨ��(0--3)��λ2��1��ʾ���Σ�0��ʾ�������� Ȼ����

    // DMA�������˿�12��11д�뷽ʽ�֣�������0x46��д������0x4A���� ��д�봫��ʹ��

    // ��������ַaddr����Ҫ������ֽ���0x3ff��0--1023�������λ��DMAͨ��2�����Σ�

    // ����DMA2����DREQ�źš�

171 /* mask DMA 2 */    /* ����DMAͨ��2 */

172         immoutb_p(4|2,10);

173 /* output command byte. I don't know why, but everyone (minix, */

174 /* sanches & canton) output this twice, first to 12 then to 11 */

    /* ��������ֽڡ����Dz�֪��Ϊʲô������ÿ���ˣ�minix��*/

    /* sanches��canton����������Σ�������12�ڣ�Ȼ����11�� */

    // ����Ƕ���������DMA�������ġ�����Ⱥ󴥷������˿�12�ͷ�ʽ�Ĵ����˿�11д��

    // ��ʽ�֣�����ʱ��0x46��д����0x4A����

    // ���ڸ�ͨ���ĵ�ַ�ͼ����Ĵ�������16λ�ģ��������������ʱ����Ҫ��2�ν��в�����

    // һ�η��ʵ��ֽڣ���һ�η��ʸ��ֽڡ���ʵ����д�ĸ��ֽ������Ⱥ󴥷�����״̬������

    // ��������Ϊ0ʱ������ʵ��ֽڣ����ֽڴ�����Ϊ1ʱ������ʸ��ֽڡ�ÿ����һ�Σ�

    // �ô�������״̬�ͱ仯һ�Ρ���д�˿�12�Ϳ��Խ��������ó�0״̬���Ӷ���16λ�Ĵ�

    // �������ôӵ��ֽڿ�ʼ��

175         __asm__("outb %%al,$12\n\tjmp 1f\n1:\tjmp 1f\n1:\t"

176         "outb %%al,$11\n\tjmp 1f\n1:\tjmp 1f\n1:"::

177         "a" ((char) ((command == FD_READ)?DMA_READ:DMA_WRITE)));

178 /* 8 low bits of addr */     /* ��ַ��0-7λ */

    // ��DMAͨ��2д���/��ǰ��ַ�Ĵ������˿�4����

179         immoutb_p(addr,4);

180         addr >>= 8;

181 /* bits 8-15 of addr */    /* ��ַ��8-15λ */

182         immoutb_p(addr,4);

183         addr >>= 8;

184 /* bits 16-19 of addr */    /* ��ַ16-19λ */

    // DMAֻ������1MB�ڴ�ռ���Ѱַ�����16-19λ��ַ�����ҳ��Ĵ���(�˿�0x81)��

185         immoutb_p(addr,0x81);

186 /* low 8 bits of count-1 (1024-1=0x3ff) */  /* ��������8λ(1024-1 = 0x3ff) */

    // ��DMAͨ��2д���/��ǰ�ֽڼ�����ֵ���˿�5����

187         immoutb_p(0xff,5);

188 /* high 8 bits of count-1 */    /* ��������8λ */

    // һ�ι�����1024�ֽڣ�������������

189         immoutb_p(3,5);

190 /* activate DMA 2 */    /* ����DMAͨ��2������ */

191         immoutb_p(0|2,10);

192         sti();

193 }

194

    //// ���������������һ���ֽ�����������

    // �������������һ���ֽ�֮ǰ����������Ҫ����׼����״̬���������ݴ��䷽���������

    // �ɴ�CPU �� FDC����˺�����Ҫ���ȶ�ȡ������״̬��Ϣ������ʹ����ѭ����ѯ��ʽ����

    // ���ʵ���ʱ����������������ø�λ��־reset��

195 static void output_byte(char byte)

196 {

197         int counter;

198         unsigned char status;

199

    // ѭ����ȡ��״̬������FD_STATUS��0x3f4����״̬���������״̬�� STATUS_READY ����

    // ����λSTATUS_DIR = 0��CPU��FDC�����������ݶ˿����ָ���ֽڡ�

200         if (reset)

201                 return;

202         for(counter = 0 ; counter < 10000 ; counter++) {

203                 status = inb_p(FD_STATUS) & (STATUS_READY | STATUS_DIR);

204                 if (status == STATUS_READY) {

205                         outb(byte,FD_DATA);

206                         return;

207                 }

208         }

    // �����ѭ��1��ν��������ܷ��ͣ����ø�λ��־������ӡ������Ϣ��

209         reset = 1;

210         printk("Unable to send byte to FDC\n\r");

211 }

212

    //// ��ȡFDCִ�еĽ����Ϣ��

    // �����Ϣ���7���ֽڣ����������reply_buffer[]�С����ض���Ľ���ֽ�����������

    // ֵ = -1�����ʾ��������������ʽ�����溯�����ơ�

213 static int result(void)

214 {

215         int i = 0, counter, status;

216

    // ����λ��־����λ���������˳���ȥִ�к��������еĸ�λ����������ѭ����ȡ��״̬��

    // ����FD_STATUS��0x3f4����״̬�������ȡ�Ŀ�����״̬��READY����ʾ�Ѿ�û�����ݿ�

    // ȡ���򷵻��Ѷ�ȡ���ֽ���i�����������״̬�Ƿ����־��λ��CPUßFDC������׼���á�

    // æ����ʾ�����ݿɶ�ȡ�� ���ǰѿ������еĽ�����ݶ��뵽Ӧ���������С� ����ȡ

    // MAX_REPLIES��7�����ֽڡ�

217         if (reset)

218                 return -1;

219         for (counter = 0 ; counter < 10000 ; counter++) {

220                 status = inb_p(FD_STATUS)&(STATUS_DIR|STATUS_READY|STATUS_BUSY);

221                 if (status == STATUS_READY)

222                         return i;

223                 if (status == (STATUS_DIR|STATUS_READY|STATUS_BUSY)) {

224                         if (i >= MAX_REPLIES)

225                                 break;

226                         reply_buffer[i++] = inb_p(FD_DATA);

227                 }

228         }

    // �����ѭ��1��ν��������ܷ��ͣ����ø�λ��־������ӡ������Ϣ��

229         reset = 1;

230         printk("Getstatus times out\n\r");

231         return -1;

232 }

233

    //// ���̶�д��������������

    // �ú����������̶�д����������ȷ����Ҫ��ȡ�Ľ�һ���ж��������ǰ���������������

    // �������ڹ涨������������MAX_ERRORS��8�Σ������ٶԵ�ǰ����������һ���IJ���

    // ���ԡ������/д���������Ѿ�����MAX_ERRORS/2������Ҫ����������λ��������������

    // ��λ��־reset�������������������������ֵ��һ�룬��ֻ������У��һ�´�ͷλ�ã�

    // ������������У����־recalibrate�������ĸ�λ������У���������ں����ij����н��С�

234 static void bad_flp_intr(void)

235 {

    // ���Ȱѵ�ǰ���������������1�������ǰ������������������������������������ȡ

    // ��ѡ����ǰ�����������������������������û�б����£���

236         CURRENT->errors++;

237         if (CURRENT->errors > MAX_ERRORS) {

238                 floppy_deselect(current_drive);

239                 end_request(0);

240         }

    // �����ǰ����������������������������������һ�룬���ø�λ��־������������и�

    // λ������Ȼ�����ԡ���������������У��һ�����ԡ�

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

242                 reset = 1;

243         else

244                 recalibrate = 1;

245 }      

246

247 /*

248  * Ok, this interrupt is called after a DMA read/write has succeeded,

249  * so we check the results, and copy any buffers.

250  */

    /*

     * OK��������жϴ�����������DMA��/д�ɹ�����õģ��������ǾͿ��Լ��

     * ִ�н���������ƻ������е����ݡ�

     */

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

    // �ú��������������������������������жϴ��������б����á��������ȶ�ȡ�������״

    // ̬��Ϣ���ݴ��жϲ����Ƿ�������Ⲣ����Ӧ������ �����/д�����ɹ�����ô��������

    // �Ƕ����������仺�������ڴ�1MB����λ�ã�����Ҫ�����ݴ�������ʱ���������Ƶ�����

    // ��Ļ�������

251 static void rw_interrupt(void)

252 {

    // ��ȡFDCִ�еĽ����Ϣ��������ؽ���ֽ���������7������״̬�ֽ�0��1��2�д���

    // ������־����ô����д��������ʾ������Ϣ���ͷŵ�ǰ����������������ǰ���������

    // ��ִ�г�������������Ȼ�����ִ���������������������״̬�ĺ���μ�fdreg.h�ļ���

    // ( 0xf8 = ST0_INTR | ST0_SE | ST0_ECE | ST0_NR )

    // ( 0xbf = ST1_EOC | ST1_CRC | ST1_OR | ST1_ND | ST1_WP | ST1_MAM��Ӧ����0xb7)

    // ( 0x73 = ST2_CM | ST2_CRC | ST2_WC | ST2_BC | ST2_MAM )

253         if (result() != 7 || (ST0 & 0xf8) || (ST1 & 0xbf) || (ST2 & 0x73)) {

254                 if (ST1 & 0x02) {         // 0x02 = ST1_WP - Write Protected��

255                         printk("Drive %d is write protected\n\r",current_drive);

256                         floppy_deselect(current_drive);

257                         end_request(0);

258                 } else

259                         bad_flp_intr();

260                 do_fd_request();

261                 return;

262         }

    // �����ǰ������Ļ�����λ��1MB��ַ���ϣ���˵���˴����̶����������ݻ�������ʱ��

    // �����ڣ���Ҫ���Ƶ���ǰ������Ļ������У���ΪDMAֻ����1MB��ַ��ΧѰַ�������

    // �ͷŵ�ǰ������ȡ��ѡ������ִ�е�ǰ������������������ѵȴ���������Ľ��У�����

    // �ȴ�����������Ľ��̣����еĻ������������豸������������ɾ����������ټ���ִ

    // ���������������������

263         if (command == FD_READ && (unsigned long)(CURRENT->buffer) >= 0x100000)

264                 copy_buffer(tmp_floppy_area,CURRENT->buffer);

265         floppy_deselect(current_drive);

266         end_request(1);

267         do_fd_request();

268 }

269

    //// ����DMAͨ��2�������̿������������Ͳ��������1�ֽ����� + 0~7�ֽڲ�������

    // ��reset��־û����λ����ô�ڸú����˳��������̿�����ִ������Ӧ��/д������ͻ�

    // ����һ�������ж����󣬲���ʼִ�������жϴ�������

270 inline void setup_rw_floppy(void)

271 {

272         setup_DMA();               // ��ʼ������DMAͨ����

273         do_floppy = rw_interrupt;  // �������жϵ��ú���ָ�롣

274         output_byte(command);      // ���������ֽڡ�

275         output_byte(head<<2 | current_drive);  // ��������ͷ��+�������š�

276         output_byte(track);        // �������ŵ��š�

277         output_byte(head);         // ��������ͷ�š�

278         output_byte(sector);       // ��������ʼ�����š�

279         output_byte(2);         /* sector size = 512 */ // ������(N=2)512�ֽڡ�

280         output_byte(floppy->sect); // ������ÿ�ŵ���������

281         output_byte(floppy->gap);  // ����������������ȡ�

282         output_byte(0xFF);      /* sector size (0xff when n!=0 ?) */

                                    // ��������N=0ʱ������������ֽڳ��ȣ��������á�

    // �������κ�һ��output_byte()����������������ø�λ��־reset����ʱ��������ȥִ��

    // do_fd_request()�еĸ�λ�������롣

283         if (reset)

284                 do_fd_request();

285 }

286

287 /*

288  * This is the routine called after every seek (or recalibrate) interrupt

289  * from the floppy controller. Note that the "unexpected interrupt" routine

290  * also does a recalibrate, but doesn't come here.

291  */

    /*

     * ���ӳ�������ÿ�����̿�����Ѱ����������У�����ж��б����õġ�ע��

     * "unexpected interrupt"(�����ж�)�ӳ���Ҳ��ִ������У�������������ڴ˵ء�

     */

    //// Ѱ�������������жϹ����е��õ�C������

    // ���ȷ��ͼ���ж�״̬������״̬��ϢST0�ʹ�ͷ���ڴŵ���Ϣ����������ִ�д���

    // ������⴦����ȡ���������̲���������������״̬��Ϣ���õ�ǰ�ŵ�������Ȼ���

    // �ú���setup_rw_floppy()����DMA��������̶�д����Ͳ�����

292 static void seek_interrupt(void)

293 {

    // ���ȷ��ͼ���ж�״̬����Ի�ȡѰ������ִ�еĽ��������������������ؽ����

    // Ϣ�������ֽڣ�ST0�ʹ�ͷ��ǰ�ŵ��š�Ȼ���ȡFDCִ�еĽ����Ϣ�� ������ؽ����

    // ����������2������ST0��ΪѰ�����������ߴ�ͷ���ڴŵ���ST1���������趨�ŵ�����˵

    // �������˴�������ִ�м��������������Ȼ�����ִ�������������ִ�и�λ������

294 /* sense drive status */    /* ���������״̬ */

295         output_byte(FD_SENSEI);

296         if (result() != 2 || (ST0 & 0xF8) != 0x20 || ST1 != seek_track) {

297                 bad_flp_intr();

298                 do_fd_request();

299                 return;

300         }

    // ��Ѱ�������ɹ��������ִ�е�ǰ����������̲������������̿�������������Ͳ�����

301         current_track = ST1;       // ���õ�ǰ�ŵ���

302         setup_rw_floppy();         // ����DMA��������̲�������Ͳ�����

303 }

304

305 /*

306  * This routine is called when everything should be correctly set up

307  * for the transfer (ie floppy motor is on and the correct floppy is

308  * selected).

309  */

    /*

     * �ú������ڴ��������������Ϣ����ȷ���úú󱻵��õģ������������ѿ���

     * ������ѡ������ȷ�����̣���������

     */

    //// ��д���ݴ��亯����

310 static void transfer(void)

311 {

    // ���ȼ�鵱ǰ�����������Ƿ����ָ���������IJ����������Ǿͷ���������������������

    // ����Ӧ����������1����4λ�������ʣ�����λ��ͷж��ʱ�䣻����2����ͷ����ʱ�䣩��

    // Ȼ���жϵ�ǰ���ݴ��������Ƿ���ָ����������һ�£������Ǿͷ���ָ������������ֵ��

    // ���ݴ������ʿ��ƼĴ���(FD_DCR)��

312         if (cur_spec1 != floppy->spec1) {          // ��⵱ǰ������

313                 cur_spec1 = floppy->spec1;

314                 output_byte(FD_SPECIFY);           // �������ô��̲������

315                 output_byte(cur_spec1);            /* hut etc */  // ���Ͳ�����

316                 output_byte(6);                    /* Head load time =6ms, DMA */

317         }

318         if (cur_rate != floppy->rate)              // ��⵱ǰ���ʡ�

319                 outb_p(cur_rate = floppy->rate,FD_DCR);

    // �������κ�һ��output_byte()����ִ�г�������λ��־reset�ͻᱻ��λ���������

    // ������Ҫ���һ��reset��־����reset��ı���λ�ˣ�������ȥִ��do_fd_request()

    // �еĸ�λ�������롣

320         if (reset) {

321                 do_fd_request();

322                 return;

323         }

    // �����ʱѰ����־Ϊ�㣨������ҪѰ������������DMA�������̿�����������Ӧ��������

    // �Ͳ����󷵻ء������ִ��Ѱ�����������������������жϴ������ú���ΪѰ���жϺ�����

    // �����ʼ�ŵ��Ų����������ʹ�ͷѰ������Ͳ�������ʹ�õIJ������ǵ�112--121��

    // �����õ�ȫ�ֱ���ֵ�������ʼ�ŵ���seek_trackΪ0����ִ������У�������ô�ͷ����

    // λ��

324         if (!seek) {

325                 setup_rw_floppy();                   // ������������顣

326                 return;

327         }

328         do_floppy = seek_interrupt;                  // Ѱ���жϵ��õ�C������

329         if (seek_track) {                            // ��ʼ�ŵ��š�

330                 output_byte(FD_SEEK);                // ���ʹ�ͷѰ�����

331                 output_byte(head<<2 | current_drive);// ���Ͳ�������ͷ��+��ǰ�����š�

332                 output_byte(seek_track);             // ���Ͳ������ŵ��š�

333         } else {

334                 output_byte(FD_RECALIBRATE);         // ��������У�������ͷ���㣩��

335                 output_byte(head<<2 | current_drive);// ���Ͳ�������ͷ��+��ǰ�����š�

336         }

    // ͬ���أ��������κ�һ��output_byte()����ִ�г�������λ��־reset�ͻᱻ��λ��

    // ��reset��ı���λ�ˣ�������ȥִ��do_fd_request()�еĸ�λ�������롣

337         if (reset)

338                 do_fd_request();

339 }

340

341 /*

342  * Special case - used after a unexpected interrupt (or reset)

343  */

    /*

     * ������� - ���������жϣ���λ��������

     */

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

    // ���ȷ��ͼ���ж�״̬����޲�������������ؽ���������������ø�λ��־����������

    // У����־���㡣Ȼ���ٴ�ִ���������������������Ӧ������

344 static void recal_interrupt(void)

345 {

346         output_byte(FD_SENSEI);                  // ���ͼ���ж�״̬���

347         if (result()!=2 || (ST0 & 0xE0) == 0x60) // ������ؽ���ֽ���������2������

348                 reset = 1;                       // �쳣���������ø�λ��־��

349         else

350                 recalibrate = 0;                 // ����λ����У����־��

351         do_fd_request();                         // ����Ӧ������

352 }

353

    //// ���������ж����������������жϴ��������е��õĺ�����

    // ���ȷ��ͼ���ж�״̬����޲�������������ؽ���������������ø�λ��־������������

    // У����־��

354 void unexpected_floppy_interrupt(void)

355 {

356         output_byte(FD_SENSEI);                  // ���ͼ���ж�״̬���

357         if (result()!=2 || (ST0 & 0xE0) == 0x60) // ������ؽ���ֽ���������2������

358                 reset = 1;                       // �쳣���������ø�λ��־��

359         else

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

361 }

362

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

    // �����̿�����FDC��������У������Ͳ���������λ����У����־�������̿�����ִ����

    // ����У������ͻ����������������ж��е���recal_interrupt()������

363 static void recalibrate_floppy(void)

364 {

365         recalibrate = 0;                         // ��λ����У����־��

366         current_track = 0;                       // ��ǰ�ŵ��Ź��㡣

367         do_floppy = recal_interrupt;             // ָ������У���жϵ��õ�C������

368         output_byte(FD_RECALIBRATE);             // �������У����

369         output_byte(head<<2 | current_drive);    // ��������ͷ�� + ��ǰ�������š�

    // �������κ�һ��output_byte()����ִ�г�������λ��־reset�ͻᱻ��λ���������

    // ������Ҫ���һ��reset��־����reset��ı���λ�ˣ�������ȥִ��do_fd_request()

    // �еĸ�λ�������롣

370         if (reset)

371                 do_fd_request();

372 }

373

    //// ���̿�����FDC��λ�жϵ��ú�����

    // �ú�������������������˸�λ��������������������жϴ��������б����á�

    // ���ȷ��ͼ���ж�״̬����޲�������Ȼ��������صĽ���ֽڡ����ŷ����趨����

    // �����������ز���������ٴε��������������do_fd_request() ȥִ������У��

    // ������������ִ��output_byte() ��������ʱ��λ��־�ֻᱻ��λ�����Ҳ�����ٴ�ȥ

    // ִ�и�λ������

374 static void reset_interrupt(void)

375 {

376         output_byte(FD_SENSEI);                  // ���ͼ���ж�״̬���

377         (void) result();                         // ��ȡ����ִ�н���ֽڡ�

378         output_byte(FD_SPECIFY);                 // �����趨�����������

379         output_byte(cur_spec1);                  /* hut etc */  // ���Ͳ�����

380         output_byte(6);                          /* Head load time =6ms, DMA */

381         do_fd_request();                         // ����ִ����������

382 }

383

384 /*

385  * reset is done by pulling bit 2 of DOR low for a while.

386  */

    /* FDC��λ��ͨ������������Ĵ���(DOR)λ2��0һ���ʵ�ֵ� */

    //// ��λ���̿�������

    // �ú����������ò����ͱ�־���Ѹ�λ��־��0��Ȼ�����������cur_spec1��cur_rate

    // ��Ϊ��Ч����Ϊ��λ��������������������Ҫ�������á�����������Ҫ����У����־��

    // ������FDCִ�и�λ�����������������ж��е��õ�C����reset_interrupt()�����

    // ��DOR�Ĵ���λ2��0һ����Զ�����ִ�и�λ��������ǰ��������Ĵ���DOR��λ2

    // ������/��λ����λ��

387 static void reset_floppy(void)

388 {

389         int i;

390

391         reset = 0;                            // ��λ��־��0��

392         cur_spec1 = -1;                       // ʹ��Ч��

393         cur_rate = -1;

394         recalibrate = 1;                      // ����У����־��λ��

395         printk("Reset-floppy called\n\r");    // ��ʾִ�����̸�λ������Ϣ��

396         cli();                                // ���жϡ�

397         do_floppy = reset_interrupt;          // �������жϴ��������е��õĺ�����

398         outb_p(current_DOR & ~0x04,FD_DOR);   // �����̿�����FDCִ�и�λ������

399         for (i=0 ; i<100 ; i++)               // �ղ������ӳ١�

400                 __asm__("nop");

401         outb(current_DOR,FD_DOR);             // ���������̿�������

402         sti();                                // ���жϡ�

403 }

404

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

    // ��ִ��һ��������Ҫ��IJ���֮ǰ��Ϊ�˵ȴ�ָ������������ת�������������Ĺ���ת�٣�

    // do_fd_request()����Ϊ׼���õĵ�ǰ������������һ����ʱ��ʱ�������������Ǹö�ʱ��

    // ����ʱ���õĺ����������ȼ����������Ĵ���(DOR)��ʹ��ѡ��ǰָ������������Ȼ��

    // ����ִ�����̶�д���亯��transfer()��

405 static void floppy_on_interrupt(void)           // floppy_on() interrupt��

406 {

407 /* We cannot do a floppy-select, as that might sleep. We just force it */

    /* ���Dz�����������ѡ�����������Ϊ����ܻ��������˯�ߡ�����ֻ����ʹ���Լ�ѡ�� */

    // �����ǰ������������������Ĵ���DOR�еIJ�ͬ������Ҫ��������DORΪ��ǰ��������

    // ������������Ĵ��������ǰDOR�Ժ�ʹ�ö�ʱ���ӳ�2���δ�ʱ�䣬��������õ�ִ

    // �С�Ȼ��������̶�д���亯��transfer()������ǰ��������DOR�е��������ô�Ϳ���

    // ֱ�ӵ������̶�д���亯����

408         selected = 1;                          // ����ѡ����ǰ��������־��

409         if (current_drive != (current_DOR & 3)) {

410                 current_DOR &= 0xFC;

411                 current_DOR |= current_drive;

412                 outb(current_DOR,FD_DOR);      // ����������Ĵ��������ǰDOR��

413                 add_timer(2,&transfer);        // ���Ӷ�ʱ����ִ�д��亯����

414         } else

415                 transfer();                    // ִ�����̶�д���亯����

416 }

417

    //// ���̶�д�������������

    // �ú�����������������������Ҫ�ĺ�������Ҫ�����ǣ��ٴ����и�λ��־������У����־��

    // λ������������������е��豸�ż���ȡ��������ָ�������IJ����飻�������ںӶ�ʱ����

    // �����̶�/д������

418 void do_fd_request(void)

419 {

420         unsigned int block;

421

    // ���ȼ���Ƿ��и�λ��־������У����־��λ�������򱾺�����ִ����ر�־�Ĵ�������

    // ��ͷ��ء������λ��־����λ����ִ�����̸�λ���������ء��������У����־����λ��

    // ��ִ����������У�����������ء�

422         seek = 0;                              // ��Ѱ����־��

423         if (reset) {                           // ��λ��־����λ��

424                 reset_floppy();

425                 return;

426         }

427         if (recalibrate) {                     // ����У����־����λ��

428                 recalibrate_floppy();

429                 return;

430         }

    // ���������������ܴ����↑ʼ����������blk.h�ļ��е�INIT_REQUEST��������������

    // �Ϸ��ԣ������û�����������˳����μ�blk.h,127����Ȼ�������������е��豸��ȡ����

    // ����ָ�������IJ����顣��������齫�����������������̲���ʹ�õ�ȫ�ֱ��������飨��

    // ��112 - 122�У����������豸���е��������� (MINOR(CURRENT->dev)>>2) ������������

    // ������floppy_type[]������ֵ��ȡ��ָ�������IJ����顣

431         INIT_REQUEST;

432         floppy = (MINOR(CURRENT->dev)>>2) + floppy_type;

 

    // ���濪ʼ����112--122���ϵ�ȫ�ֱ���ֵ�������ǰ��������current_drive����������

    // ��ָ�����������ţ����ñ�־seek����ʾ��ִ�ж�/д����֮ǰ��Ҫ����������ִ��Ѱ����

    // ����Ȼ��ѵ�ǰ������������Ϊ��������ָ�����������š�

433         if (current_drive != CURRENT_DEV)   // CURRENT_DEV����������ָ���������š�

434                 seek = 1;

435         current_drive = CURRENT_DEV;

 

    // ���ö�д��ʼ����block����Ϊÿ�ζ�д���Կ�Ϊ��λ��1��Ϊ2����������������ʼ����

    // ��Ҫ����ȴ�����������С2������������˵����������������Ч�������ô�����������

    // ȥִ����һ�������

436         block = CURRENT->sector;            // ȡ��ǰ��������������ʼ�����š�

437         if (block+2 > floppy->size) {       // ���block + 2���ڴ�������������

438                 end_request(0);             // ������������������

439                 goto repeat;

440         }

    // �����Ӧ�ڴŵ��ϵ������š���ͷ�š��ŵ��š���Ѱ�ŵ��ţ�������������ͬ��ʽ���̣���

441         sector = block % floppy->sect;   // ��ʼ������ÿ�ŵ�������ȡģ���ôŵ��������š�

442         block /= floppy->sect;           // ��ʼ������ÿ�ŵ�������ȡ��������ʼ�ŵ�����

443         head = block % floppy->head;     // ��ʼ�ŵ����Դ�ͷ��ȡģ���ò����Ĵ�ͷ�š�

444         track = block / floppy->head;    // ��ʼ�ŵ����Դ�ͷ��ȡ�����ò����Ĵŵ��š�

445         seek_track = track << floppy->stretch; // ��Ӧ�������������ͽ��е�������Ѱ���š�

 

    // �ٿ����Ƿ���Ҫ����ִ��Ѱ�����������Ѱ�����뵱ǰ��ͷ���ڴŵ��Ų�ͬ������Ҫ����

    // Ѱ����������������ҪѰ����־seek�������������ִ�е���������command��

446         if (seek_track != current_track)

447                 seek = 1;

448         sector++;                        // ������ʵ�����������Ǵ�1����

449         if (CURRENT->cmd == READ)        // ����������Ƕ����������ö������롣

450                 command = FD_READ;

451         else if (CURRENT->cmd == WRITE)  // �����������д����������д�����롣

452                 command = FD_WRITE;

453         else

454                 panic("do_fd_request: unknown command");

    // ���������ú� 112--122��������ȫ�ֱ���ֵ֮�����ǿ��Կ�ʼִ������������ˡ��ò�

    // �����ö�ʱ������������ΪΪ���ܶ��������ж�д��������Ҫ�����������������ﲢ�ﵽ��

    // ����ת�ٶȡ�������Ҫһ����ʱ�䡣����������� ticks_to_floppy_on() ������������ʱ

    // ʱ�䣬Ȼ��ʹ�ø���ʱ�趨һ����ʱ������ʱ�䵽ʱ�͵��ú���floppy_on_interrupt()��

455         add_timer(ticks_to_floppy_on(current_drive),&floppy_on_interrupt);

456 }

457

    // ���������������̺��е����ݿ�������

458 static int floppy_sizes[] ={

459            0,   0,   0,   0,

460          360, 360 ,360, 360,

461         1200,1200,1200,1200,

462          360, 360, 360, 360,

463          720, 720, 720, 720,

464          360, 360, 360, 360,

465          720, 720, 720, 720,

466         1440,1440,1440,1440

467 };

468

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

    // �������̿��豸������Ĵ�������do_fd_request()�������������ж��ţ�int 0x26����Ӧ

    // Ӳ���ж������ź�IRQ6���� Ȼ��ȡ���Ը��ж��źŵ����Σ����������̿�����FDC������

    // �������źš��ж���������IDT�����������������ú�set_trap_gate()������ͷ�ļ�

    // include/asm/system.h�С�

469 void floppy_init(void)

470 {

    // ���������ж�����������floppy_interrupt��kernel/sys_call.s��267�У������жϴ���

    // ���̡��жϺ�Ϊint 0x26��38������Ӧ8259AоƬ�ж������ź�IRQ6��

471         blk_size[MAJOR_NR] = floppy_sizes;

472         blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;  // = do_fd_request()��

473         set_trap_gate(0x26,&floppy_interrupt);          // ������������������

474         outb(inb_p(0x21)&~0x40,0x21);                   // ��λ�����ж���������λ��

475 }

476