56.html

来自「linux 0.11中文版 有注释」· HTML 代码 · 共 509 行 · 第 1/4 页

HTML
509
字号
<a name='L355'><font color='red'>}</font>
<a name='L356'>
<a name='L357'><i><font color='green'>//// 写扇区中断调用函数。在硬盘中断处理程序中被调用。</font></i>
<a name='L358'><i><font color='green'>// 在写命令执行后,会产生硬盘中断信号,执行硬盘中断处理程序,此时在硬盘中断处理程序中调用的</font></i>
<a name='L359'><i><font color='green'>// C 函数指针do_hd()已经指向write_intr(),因此会在写操作完成(或出错)后,执行该函数。</font></i>
<a name='L360'><b>static</b> <b>void</b> <a href='../R/736.html' title='Multiple refered from 2 places.'>write_intr</a> (<b>void</b>)
<a name='L361'><font color='red'>{</font>
<a name='L362'>  <b>if</b> (<a href='../S/56.html#L237' title='Defined at 237 in kernel/blk_drv/hd.c.'>win_result</a> ())
<a name='L363'>    <font color='red'>{</font>                           <i><font color='green'>// 如果硬盘控制器返回错误信息,</font></i>
<a name='L364'>      <a href='../S/56.html#L326' title='Defined at 326 in kernel/blk_drv/hd.c.'>bad_rw_intr</a> ();           <i><font color='green'>// 则首先进行硬盘读写失败处理,</font></i>
<a name='L365'>      <a href='../S/56.html#L390' title='Defined at 390 in kernel/blk_drv/hd.c.'>do_hd_request</a> ();         <i><font color='green'>// 然后再次请求硬盘作相应(复位)处理,</font></i>
<a name='L366'>      <b>return</b>;                   <i><font color='green'>// 然后返回(也退出了此次硬盘中断)。</font></i>
<a name='L367'>    <font color='red'>}</font>
<a name='L368'>  <b>if</b> (--<a href='../S/54.html#L116' title='Defined at 116 in kernel/blk_drv/blk.h.'>CURRENT</a>-&gt;nr_sectors)
<a name='L369'>    <font color='red'>{</font>                           <i><font color='green'>// 否则将欲写扇区数减1,若还有扇区要写,则</font></i>
<a name='L370'>      <a href='../S/54.html#L116' title='Defined at 116 in kernel/blk_drv/blk.h.'>CURRENT</a>-&gt;sector++;        <i><font color='green'>// 当前请求起始扇区号+1,</font></i>
<a name='L371'>      <a href='../S/54.html#L116' title='Defined at 116 in kernel/blk_drv/blk.h.'>CURRENT</a>-&gt;buffer += 512;   <i><font color='green'>// 调整请求缓冲区指针,</font></i>
<a name='L372'>      do_hd = &amp;<a href='../S/56.html#L360' title='Defined at 360 in kernel/blk_drv/hd.c.'>write_intr</a>;      <i><font color='green'>// 置硬盘中断程序调用函数指针为write_intr(),</font></i>
<a name='L373'>      <a href='../S/56.html#L95' title='Defined at 95 in kernel/blk_drv/hd.c.'>port_write</a> (<a href='../S/32.html#L15' title='Defined at 15 in include/linux/hdreg.h.'>HD_DATA</a>, <a href='../S/54.html#L116' title='Defined at 116 in kernel/blk_drv/blk.h.'>CURRENT</a>-&gt;buffer, 256);       <i><font color='green'>// 再向数据寄存器端口写256 字节。</font></i>
<a name='L374'>      <b>return</b>;                   <i><font color='green'>// 返回等待硬盘再次完成写操作后的中断处理。</font></i>
<a name='L375'>    <font color='red'>}</font>
<a name='L376'>  <a href='../S/54.html#L136' title='Defined at 136 in kernel/blk_drv/blk.h.'>end_request</a> (1);              <i><font color='green'>// 若全部扇区数据已经写完,则处理请求结束事宜,</font></i>
<a name='L377'>  <a href='../S/56.html#L390' title='Defined at 390 in kernel/blk_drv/hd.c.'>do_hd_request</a> ();             <i><font color='green'>// 执行其它硬盘请求操作。</font></i>
<a name='L378'><font color='red'>}</font>
<a name='L379'>
<a name='L380'><i><font color='green'>//// 硬盘重新校正(复位)中断调用函数。在硬盘中断处理程序中被调用。</font></i>
<a name='L381'><i><font color='green'>// 如果硬盘控制器返回错误信息,则首先进行硬盘读写失败处理,然后请求硬盘作相应(复位)处理。</font></i>
<a name='L382'><b>static</b> <b>void</b> <a href='../R/567.html' title='Multiple refered from 3 places.'>recal_intr</a> (<b>void</b>)
<a name='L383'><font color='red'>{</font>
<a name='L384'>  <b>if</b> (<a href='../S/56.html#L237' title='Defined at 237 in kernel/blk_drv/hd.c.'>win_result</a> ())
<a name='L385'>    <a href='../S/56.html#L326' title='Defined at 326 in kernel/blk_drv/hd.c.'>bad_rw_intr</a> ();
<a name='L386'>  <a href='../S/56.html#L390' title='Defined at 390 in kernel/blk_drv/hd.c.'>do_hd_request</a> ();
<a name='L387'><font color='red'>}</font>
<a name='L388'>
<a name='L389'><i><font color='green'>// 执行硬盘读写请求操作。</font></i>
<a name='L390'><b>void</b> <a href='../R/440.html' title='Multiple refered from 6 places.'>do_hd_request</a> (<b>void</b>)
<a name='L391'><font color='red'>{</font>
<a name='L392'>  <b>int</b> <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>, r;
<a name='L393'>  <b>unsigned</b> <b>int</b> block, <a href='../S/7.html#L136' title='Defined at 136 in fs/char_dev.c.'>dev</a>;
<a name='L394'>  <b>unsigned</b> <b>int</b> sec, head, cyl;
<a name='L395'>  <b>unsigned</b> <b>int</b> nsect;
<a name='L396'>
<a name='L397'>    <a href='../S/54.html#L156' title='Defined at 156 in kernel/blk_drv/blk.h.'>INIT_REQUEST</a>;               <i><font color='green'>// 检测请求项的合法性(参见kernel/blk_drv/blk.h,127)。</font></i>
<a name='L398'><i><font color='green'>// 取设备号中的子设备号(见列表后对硬盘设备号的说明)。子设备号即是硬盘上的分区号。</font></i>
<a name='L399'>    <a href='../S/7.html#L136' title='Defined at 136 in fs/char_dev.c.'>dev</a> = <a href='../D/238.html' title='Multiple defined in 2 places.'>MINOR</a> (<a href='../S/54.html#L116' title='Defined at 116 in kernel/blk_drv/blk.h.'>CURRENT</a>-&gt;<a href='../S/7.html#L136' title='Defined at 136 in fs/char_dev.c.'>dev</a>); <i><font color='green'>// CURRENT 定义为(blk_dev[MAJOR_NR].current_request)。</font></i>
<a name='L400'>    block = <a href='../S/54.html#L116' title='Defined at 116 in kernel/blk_drv/blk.h.'>CURRENT</a>-&gt;sector;    <i><font color='green'>// 请求的起始扇区。</font></i>
<a name='L401'><i><font color='green'>// 如果子设备号不存在或者起始扇区大于该分区扇区数-2,则结束该请求,并跳转到标号repeat 处</font></i>
<a name='L402'><i><font color='green'>// (定义在INIT_REQUEST 开始处)。因为一次要求读写2 个扇区(512*2 字节),所以请求的扇区号</font></i>
<a name='L403'><i><font color='green'>// 不能大于分区中最后倒数第二个扇区号。</font></i>
<a name='L404'>  <b>if</b> (<a href='../S/7.html#L136' title='Defined at 136 in fs/char_dev.c.'>dev</a> &gt;= 5 * <a href='../S/56.html#L63' title='Defined at 63 in kernel/blk_drv/hd.c.'>NR_HD</a> || block + 2 &gt; hd[<a href='../S/7.html#L136' title='Defined at 136 in fs/char_dev.c.'>dev</a>].nr_sects)
<a name='L405'>    <font color='red'>{</font>
<a name='L406'>      <a href='../S/54.html#L136' title='Defined at 136 in kernel/blk_drv/blk.h.'>end_request</a> (0);
<a name='L407'>      <b>goto</b> repeat;              <i><font color='green'>// 该标号在blk.h 最后面。</font></i>
<a name='L408'>    <font color='red'>}</font>
<a name='L409'>  block += hd[<a href='../S/7.html#L136' title='Defined at 136 in fs/char_dev.c.'>dev</a>].start_sect;  <i><font color='green'>// 将所需读的块对应到整个硬盘上的绝对扇区号。</font></i>
<a name='L410'>  <a href='../S/7.html#L136' title='Defined at 136 in fs/char_dev.c.'>dev</a> /= 5;                     <i><font color='green'>// 此时dev 代表硬盘号(0 或1)。</font></i>
<a name='L411'><i><font color='green'>// 下面嵌入汇编代码用来从硬盘信息结构中根据起始扇区号和每磁道扇区数计算在磁道中的</font></i>
<a name='L412'><i><font color='green'>// 扇区号(sec)、所在柱面号(cyl)和磁头号(head)。</font></i>
<a name='L413'><b>__asm__</b> ("divl %4": "=a" (block), "=d" (sec):"" (block), "1" (0),
<a name='L414'>           "r" (hd_info[<a href='../S/7.html#L136' title='Defined at 136 in fs/char_dev.c.'>dev</a>].
<a name='L415'>                sect));
<a name='L416'><b>__asm__</b> ("divl %4": "=a" (cyl), "=d" (head):"" (block), "1" (0),
<a name='L417'>           "r" (hd_info[<a href='../S/7.html#L136' title='Defined at 136 in fs/char_dev.c.'>dev</a>].
<a name='L418'>                head));
<a name='L419'>  sec++;
<a name='L420'>  nsect = <a href='../S/54.html#L116' title='Defined at 116 in kernel/blk_drv/blk.h.'>CURRENT</a>-&gt;nr_sectors;  <i><font color='green'>// 欲读/写的扇区数。</font></i>
<a name='L421'><i><font color='green'>// 如果reset 置1,则执行复位操作。复位硬盘和控制器,并置需要重新校正标志,返回。</font></i>
<a name='L422'>  <b>if</b> (reset)
<a name='L423'>    <font color='red'>{</font>
<a name='L424'>      reset = 0;
<a name='L425'>      recalibrate = 1;
<a name='L426'>      <a href='../S/56.html#L310' title='Defined at 310 in kernel/blk_drv/hd.c.'>reset_hd</a> (<a href='../S/54.html#L117' title='Defined at 117 in kernel/blk_drv/blk.h.'>CURRENT_DEV</a>);
<a name='L427'>      <b>return</b>;
<a name='L428'>    <font color='red'>}</font>
<a name='L429'><i><font color='green'>// 如果重新校正标志(recalibrate)置位,则首先复位该标志,然后向硬盘控制器发送重新校正命令。</font></i>
<a name='L430'>  <b>if</b> (recalibrate)
<a name='L431'>    <font color='red'>{</font>
<a name='L432'>      recalibrate = 0;
<a name='L433'>      <a href='../S/56.html#L254' title='Defined at 254 in kernel/blk_drv/hd.c.'>hd_out</a> (<a href='../S/7.html#L136' title='Defined at 136 in fs/char_dev.c.'>dev</a>, hd_info[<a href='../S/54.html#L117' title='Defined at 117 in kernel/blk_drv/blk.h.'>CURRENT_DEV</a>].sect, 0, 0, 0,
<a name='L434'>              <a href='../S/32.html#L41' title='Defined at 41 in include/linux/hdreg.h.'>WIN_RESTORE</a>, &amp;<a href='../S/56.html#L382' title='Defined at 382 in kernel/blk_drv/hd.c.'>recal_intr</a>);
<a name='L435'>      <b>return</b>;
<a name='L436'>    <font color='red'>}</font>
<a name='L437'><i><font color='green'>// 如果当前请求是写扇区操作,则发送写命令,循环读取状态寄存器信息并判断请求服务标志</font></i>
<a name='L438'><i><font color='green'>// DRQ_STAT 是否置位。DRQ_STAT 是硬盘状态寄存器的请求服务位(include/linux/hdreg.h,27)。</font></i>
<a name='L439'>  <b>if</b> (<a href='../S/54.html#L116' title='Defined at 116 in kernel/blk_drv/blk.h.'>CURRENT</a>-&gt;cmd == <a href='../S/31.html#L43' title='Defined at 43 in include/linux/fs.h.'>WRITE</a>)
<a name='L440'>    <font color='red'>{</font>
<a name='L441'>      <a href='../S/56.html#L254' title='Defined at 254 in kernel/blk_drv/hd.c.'>hd_out</a> (<a href='../S/7.html#L136' title='Defined at 136 in fs/char_dev.c.'>dev</a>, nsect, sec, head, cyl, <a href='../S/32.html#L43' title='Defined at 43 in include/linux/hdreg.h.'>WIN_WRITE</a>, &amp;<a href='../S/56.html#L360' title='Defined at 360 in kernel/blk_drv/hd.c.'>write_intr</a>);
<a name='L442'>      <b>for</b> (<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> = 0; <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> &lt; 3000 &amp;&amp; !(r = <a href='../S/22.html#L25' title='Defined at 25 in include/asm/io.h.'>inb_p</a> (<a href='../S/32.html#L22' title='Defined at 22 in include/linux/hdreg.h.'>HD_STATUS</a>) &amp; <a href='../S/32.html#L33' title='Defined at 33 in include/linux/hdreg.h.'>DRQ_STAT</a>); <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>++)
<a name='L443'><i><font color='green'>/* nothing */</font></i> ;
<a name='L444'><i><font color='green'>// 如果请求服务位置位则退出循环。若等到循环结束也没有置位,则此次写硬盘操作失败,去处理</font></i>
<a name='L445'><i><font color='green'>// 下一个硬盘请求。否则向硬盘控制器数据寄存器端口HD_DATA 写入1 个扇区的数据。</font></i>
<a name='L446'>      <b>if</b> (!r)
<a name='L447'>        <font color='red'>{</font>
<a name='L448'>          <a href='../S/56.html#L326' title='Defined at 326 in kernel/blk_drv/hd.c.'>bad_rw_intr</a> ();
<a name='L449'>          <b>goto</b> repeat;          <i><font color='green'>// 该标号在blk.h 最后面,也即跳到301 行。</font></i>
<a name='L450'>        <font color='red'>}</font>
<a name='L451'>      <a href='../S/56.html#L95' title='Defined at 95 in kernel/blk_drv/hd.c.'>port_write</a> (<a href='../S/32.html#L15' title='Defined at 15 in include/linux/hdreg.h.'>HD_DATA</a>, <a href='../S/54.html#L116' title='Defined at 116 in kernel/blk_drv/blk.h.'>CURRENT</a>-&gt;buffer, 256);
<a name='L452'><i><font color='green'>// 如果当前请求是读硬盘扇区,则向硬盘控制器发送读扇区命令。</font></i>
<a name='L453'>    <font color='red'>}</font>
<a name='L454'>  <b>else</b> <b>if</b> (<a href='../S/54.html#L116' title='Defined at 116 in kernel/blk_drv/blk.h.'>CURRENT</a>-&gt;cmd == <a href='../S/31.html#L42' title='Defined at 42 in include/linux/fs.h.'>READ</a>)
<a name='L455'>    <font color='red'>{</font>
<a name='L456'>      <a href='../S/56.html#L254' title='Defined at 254 in kernel/blk_drv/hd.c.'>hd_out</a> (<a href='../S/7.html#L136' title='Defined at 136 in fs/char_dev.c.'>dev</a>, nsect, sec, head, cyl, <a href='../S/32.html#L42' title='Defined at 42 in include/linux/hdreg.h.'>WIN_READ</a>, &amp;<a href='../S/56.html#L336' title='Defined at 336 in kernel/blk_drv/hd.c.'>read_intr</a>);
<a name='L457'>    <font color='red'>}</font>
<a name='L458'>  <b>else</b>
<a name='L459'>    <a href='../S/72.html#L24' title='Defined at 24 in kernel/panic.c.'>panic</a> ("unknown hd-command");
<a name='L460'><font color='red'>}</font>
<a name='L461'>
<a name='L462'><i><font color='green'>// 硬盘系统初始化。</font></i>
<a name='L463'><b>void</b> <a href='../S/52.html#L178' title='Refered from 178 in init/main.c.'>hd_init</a> (<b>void</b>)
<a name='L464'><font color='red'>{</font>
<a name='L465'>  blk_dev[<a href='../D/225.html' title='Multiple defined in 3 places.'>MAJOR_NR</a>].request_fn = <a href='../D/66.html' title='Multiple defined in 3 places.'>DEVICE_REQUEST</a>;        <i><font color='green'>// do_hd_request()。</font></i>
<a name='L466'>  <a href='../S/25.html#L33' title='Defined at 33 in include/asm/system.h.'>set_intr_gate</a> (0x2E, &amp;hd_interrupt);  <i><font color='green'>// 设置硬盘中断门向量 int 0x2E(46)。</font></i>
<a name='L467'><i><font color='green'>// hd_interrupt 在(kernel/system_call.s,221)。</font></i>
<a name='L468'>  <a href='../S/22.html#L17' title='Defined at 17 in include/asm/io.h.'>outb_p</a> (<a href='../S/22.html#L25' title='Defined at 25 in include/asm/io.h.'>inb_p</a> (0x21) &amp; 0xfb, 0x21);   <i><font color='green'>// 复位接联的主8259A int2 的屏蔽位,允许从片</font></i>
<a name='L469'><i><font color='green'>// 发出中断请求信号。</font></i>
<a name='L470'>  <a href='../S/22.html#L3' title='Defined at 3 in include/asm/io.h.'>outb</a> (<a href='../S/22.html#L25' title='Defined at 25 in include/asm/io.h.'>inb_p</a> (0xA1) &amp; 0xbf, 0xA1);     <i><font color='green'>// 复位硬盘的中断请求屏蔽位(在从片上),允许</font></i>
<a name='L471'><i><font color='green'>// 硬盘控制器发送中断请求信号。</font></i>
<a name='L472'><font color='red'>}</font>
</pre>
<hr>
<a name='BOTTOM'>
<i><font color='green'>/* [&lt;][&gt;]<a href='#L107'>[^]</a><a href='#L463'>[v]</a><a href='#TOP'>[top]</a>[bottom]<a href='../mains.html'>[index]</a><a href='../help.html'>[help]</a> */</font></i>
</body>
</html>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?