📄 56.html
字号:
<a name='L227'><font color='red'>{</font>
<a name='L228'> <b>int</b> retries = 10000;
<a name='L229'>
<a name='L230'> <b>while</b> (--retries && (<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>) & 0xc0) != 0x40);
<a name='L231'> <b>return</b> (retries); <i><font color='green'>// 返回等待循环的次数。</font></i>
<a name='L232'><font color='red'>}</font>
<a name='L233'>
<a name='L234'><i><font color='green'>//// 检测硬盘执行命令后的状态。(win_表示温切斯特硬盘的缩写)</font></i>
<a name='L235'><i><font color='green'>// 读取状态寄存器中的命令执行结果状态。返回0 表示正常,1 出错。如果执行命令错,</font></i>
<a name='L236'><i><font color='green'>// 则再读错误寄存器HD_ERROR(0x1f1)。</font></i>
<a name='L237'><b>static</b> <b>int</b> <a href='../R/734.html' title='Multiple refered from 3 places.'>win_result</a> (<b>void</b>)
<a name='L238'><font color='red'>{</font>
<a name='L239'> <b>int</b> <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> = <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>); <i><font color='green'>// 取状态信息。</font></i>
<a name='L240'>
<a name='L241'> <b>if</b> ((<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> & (<a href='../S/32.html#L37' title='Defined at 37 in include/linux/hdreg.h.'>BUSY_STAT</a> | <a href='../S/32.html#L36' title='Defined at 36 in include/linux/hdreg.h.'>READY_STAT</a> | <a href='../S/32.html#L35' title='Defined at 35 in include/linux/hdreg.h.'>WRERR_STAT</a> | <a href='../S/32.html#L34' title='Defined at 34 in include/linux/hdreg.h.'>SEEK_STAT</a> | <a href='../S/32.html#L30' title='Defined at 30 in include/linux/hdreg.h.'>ERR_STAT</a>))
<a name='L242'> == (<a href='../S/32.html#L36' title='Defined at 36 in include/linux/hdreg.h.'>READY_STAT</a> | <a href='../S/32.html#L34' title='Defined at 34 in include/linux/hdreg.h.'>SEEK_STAT</a>))
<a name='L243'> <b>return</b> (0); <i><font color='green'>/* ok */</font></i>
<a name='L244'> <b>if</b> (<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> & 1)
<a name='L245'> <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> = <a href='../D/842.html' title='Multiple defined in 2 places.'>inb</a> (<a href='../S/32.html#L16' title='Defined at 16 in include/linux/hdreg.h.'>HD_ERROR</a>); <i><font color='green'>// 若ERR_STAT 置位,则读取错误寄存器。</font></i>
<a name='L246'> <b>return</b> (1);
<a name='L247'><font color='red'>}</font>
<a name='L248'>
<a name='L249'><i><font color='green'>//// 向硬盘控制器发送命令块(参见列表后的说明)。</font></i>
<a name='L250'><i><font color='green'>// 调用参数:drive - 硬盘号(0-1); nsect - 读写扇区数;</font></i>
<a name='L251'><i><font color='green'>// sect - 起始扇区; head - 磁头号;</font></i>
<a name='L252'><i><font color='green'>// cyl - 柱面号; cmd - 命令码;</font></i>
<a name='L253'><i><font color='green'>// *intr_addr() - 硬盘中断处理程序中将调用的C 处理函数。</font></i>
<a name='L254'><b>static</b> <b>void</b> <a href='../R/495.html' title='Multiple refered from 4 places.'>hd_out</a> (<b>unsigned</b> <b>int</b> drive, <b>unsigned</b> <b>int</b> nsect, <b>unsigned</b> <b>int</b> sect,
<a name='L255'> <b>unsigned</b> <b>int</b> head, <b>unsigned</b> <b>int</b> cyl, <b>unsigned</b> <b>int</b> cmd,
<a name='L256'> <b>void</b> (*intr_addr) (<b>void</b>))
<a name='L257'><font color='red'>{</font>
<a name='L258'> <b>register</b> <b>int</b> port <b>asm</b> ("dx"); <i><font color='green'>// port 变量对应寄存器dx。</font></i>
<a name='L259'>
<a name='L260'> <b>if</b> (drive > 1 || head > 15) <i><font color='green'>// 如果驱动器号(0,1)>1 或磁头号>15,则程序不支持。</font></i>
<a name='L261'> <a href='../S/72.html#L24' title='Defined at 24 in kernel/panic.c.'>panic</a> ("Trying to write bad sector");
<a name='L262'> <b>if</b> (!<a href='../S/56.html#L226' title='Defined at 226 in kernel/blk_drv/hd.c.'>controller_ready</a> ()) <i><font color='green'>// 如果等待一段时间后仍未就绪则出错,死机。</font></i>
<a name='L263'> <a href='../S/72.html#L24' title='Defined at 24 in kernel/panic.c.'>panic</a> ("HD controller not ready");
<a name='L264'> do_hd = intr_addr; <i><font color='green'>// do_hd 函数指针将在硬盘中断程序中被调用。</font></i>
<a name='L265'> <a href='../S/22.html#L17' title='Defined at 17 in include/asm/io.h.'>outb_p</a> (hd_info[drive].ctl, <a href='../S/32.html#L26' title='Defined at 26 in include/linux/hdreg.h.'>HD_CMD</a>); <i><font color='green'>// 向控制寄存器(0x3f6)输出控制字节。</font></i>
<a name='L266'> port = <a href='../S/32.html#L15' title='Defined at 15 in include/linux/hdreg.h.'>HD_DATA</a>; <i><font color='green'>// 置dx 为数据寄存器端口(0x1f0)。</font></i>
<a name='L267'> <a href='../S/22.html#L17' title='Defined at 17 in include/asm/io.h.'>outb_p</a> (hd_info[drive].wpcom >> 2, ++port); <i><font color='green'>// 参数:写预补偿柱面号(需除4)。</font></i>
<a name='L268'> <a href='../S/22.html#L17' title='Defined at 17 in include/asm/io.h.'>outb_p</a> (nsect, ++port); <i><font color='green'>// 参数:读/写扇区总数。</font></i>
<a name='L269'> <a href='../S/22.html#L17' title='Defined at 17 in include/asm/io.h.'>outb_p</a> (sect, ++port); <i><font color='green'>// 参数:起始扇区。</font></i>
<a name='L270'> <a href='../S/22.html#L17' title='Defined at 17 in include/asm/io.h.'>outb_p</a> (cyl, ++port); <i><font color='green'>// 参数:柱面号低8 位。</font></i>
<a name='L271'> <a href='../S/22.html#L17' title='Defined at 17 in include/asm/io.h.'>outb_p</a> (cyl >> 8, ++port); <i><font color='green'>// 参数:柱面号高8 位。</font></i>
<a name='L272'> <a href='../S/22.html#L17' title='Defined at 17 in include/asm/io.h.'>outb_p</a> (0xA0 | (drive << 4) | head, ++port); <i><font color='green'>// 参数:驱动器号+磁头号。</font></i>
<a name='L273'> <a href='../S/22.html#L3' title='Defined at 3 in include/asm/io.h.'>outb</a> (cmd, ++port); <i><font color='green'>// 命令:硬盘控制命令。</font></i>
<a name='L274'><font color='red'>}</font>
<a name='L275'>
<a name='L276'><i><font color='green'>//// 等待硬盘就绪。也即循环等待主状态控制器忙标志位复位。若仅有就绪或寻道结束标志</font></i>
<a name='L277'><i><font color='green'>// 置位,则成功,返回0。若经过一段时间仍为忙,则返回1。</font></i>
<a name='L278'><b>static</b> <b>int</b> <a href='../S/56.html#L302' title='Refered from 302 in kernel/blk_drv/hd.c.'>drive_busy</a> (<b>void</b>)
<a name='L279'><font color='red'>{</font>
<a name='L280'> <b>unsigned</b> <b>int</b> <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>;
<a name='L281'>
<a name='L282'> <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> < 10000; <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>++) <i><font color='green'>// 循环等待就绪标志位置位。</font></i>
<a name='L283'> <b>if</b> (<a href='../S/32.html#L36' title='Defined at 36 in include/linux/hdreg.h.'>READY_STAT</a> == (<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>) & (<a href='../S/32.html#L37' title='Defined at 37 in include/linux/hdreg.h.'>BUSY_STAT</a> | <a href='../S/32.html#L36' title='Defined at 36 in include/linux/hdreg.h.'>READY_STAT</a>)))
<a name='L284'> <b>break</b>;
<a name='L285'> <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> = <a href='../D/842.html' title='Multiple defined in 2 places.'>inb</a> (<a href='../S/32.html#L22' title='Defined at 22 in include/linux/hdreg.h.'>HD_STATUS</a>); <i><font color='green'>// 再取主控制器状态字节。</font></i>
<a name='L286'> <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> &= <a href='../S/32.html#L37' title='Defined at 37 in include/linux/hdreg.h.'>BUSY_STAT</a> | <a href='../S/32.html#L36' title='Defined at 36 in include/linux/hdreg.h.'>READY_STAT</a> | <a href='../S/32.html#L34' title='Defined at 34 in include/linux/hdreg.h.'>SEEK_STAT</a>; <i><font color='green'>// 检测忙位、就绪位和寻道结束位。</font></i>
<a name='L287'> <b>if</b> (<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> == <a href='../S/32.html#L36' title='Defined at 36 in include/linux/hdreg.h.'>READY_STAT</a> | <a href='../S/32.html#L34' title='Defined at 34 in include/linux/hdreg.h.'>SEEK_STAT</a>) <i><font color='green'>// 若仅有就绪或寻道结束标志,则返回0。</font></i>
<a name='L288'> <b>return</b> (0);
<a name='L289'> <a href='../S/73.html#L30' title='Defined at 30 in kernel/printk.c.'>printk</a> ("HD controller times out\n\r"); <i><font color='green'>// 否则等待超时,显示信息。并返回1。</font></i>
<a name='L290'> <b>return</b> (1);
<a name='L291'><font color='red'>}</font>
<a name='L292'>
<a name='L293'><i><font color='green'>//// 诊断复位(重新校正)硬盘控制器。</font></i>
<a name='L294'><b>static</b> <b>void</b> <a href='../S/56.html#L312' title='Refered from 312 in kernel/blk_drv/hd.c.'>reset_controller</a> (<b>void</b>)
<a name='L295'><font color='red'>{</font>
<a name='L296'> <b>int</b> <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>;
<a name='L297'>
<a name='L298'> <a href='../S/22.html#L3' title='Defined at 3 in include/asm/io.h.'>outb</a> (4, <a href='../S/32.html#L26' title='Defined at 26 in include/linux/hdreg.h.'>HD_CMD</a>); <i><font color='green'>// 向控制寄存器端口发送控制字节(4-复位)。</font></i>
<a name='L299'> <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> < 100; <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>++)
<a name='L300'> <a href='../S/25.html#L16' title='Defined at 16 in include/asm/system.h.'>nop</a> (); <i><font color='green'>// 等待一段时间(循环空操作)。</font></i>
<a name='L301'> <a href='../S/22.html#L3' title='Defined at 3 in include/asm/io.h.'>outb</a> (hd_info[0].ctl & 0x0f, <a href='../S/32.html#L26' title='Defined at 26 in include/linux/hdreg.h.'>HD_CMD</a>); <i><font color='green'>// 再发送正常的控制字节(不禁止重试、重读)。</font></i>
<a name='L302'> <b>if</b> (<a href='../S/56.html#L278' title='Defined at 278 in kernel/blk_drv/hd.c.'>drive_busy</a> ()) <i><font color='green'>// 若等待硬盘就绪超时,则显示出错信息。</font></i>
<a name='L303'> <a href='../S/73.html#L30' title='Defined at 30 in kernel/printk.c.'>printk</a> ("HD-controller still busy\n\r");
<a name='L304'> <b>if</b> ((<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> = <a href='../D/842.html' title='Multiple defined in 2 places.'>inb</a> (<a href='../S/32.html#L16' title='Defined at 16 in include/linux/hdreg.h.'>HD_ERROR</a>)) != 1) <i><font color='green'>// 取错误寄存器,若不等于1(无错误)则出错。</font></i>
<a name='L305'> <a href='../S/73.html#L30' title='Defined at 30 in kernel/printk.c.'>printk</a> ("HD-controller reset failed: %02x\n\r", <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>);
<a name='L306'><font color='red'>}</font>
<a name='L307'>
<a name='L308'><i><font color='green'>//// 复位硬盘nr。首先复位(重新校正)硬盘控制器。然后发送硬盘控制器命令“建立驱动器参数”,</font></i>
<a name='L309'><i><font color='green'>// 其中recal_intr()是在硬盘中断处理程序中调用的重新校正处理函数。</font></i>
<a name='L310'><b>static</b> <b>void</b> <a href='../S/56.html#L426' title='Refered from 426 in kernel/blk_drv/hd.c.'>reset_hd</a> (<b>int</b> nr)
<a name='L311'><font color='red'>{</font>
<a name='L312'> <a href='../S/56.html#L294' title='Defined at 294 in kernel/blk_drv/hd.c.'>reset_controller</a> ();
<a name='L313'> <a href='../S/56.html#L254' title='Defined at 254 in kernel/blk_drv/hd.c.'>hd_out</a> (nr, hd_info[nr].sect, hd_info[nr].sect, hd_info[nr].head - 1,
<a name='L314'> hd_info[nr].cyl, <a href='../S/32.html#L49' title='Defined at 49 in include/linux/hdreg.h.'>WIN_SPECIFY</a>, &<a href='../S/56.html#L382' title='Defined at 382 in kernel/blk_drv/hd.c.'>recal_intr</a>);
<a name='L315'><font color='red'>}</font>
<a name='L316'>
<a name='L317'><i><font color='green'>//// 意外硬盘中断调用函数。</font></i>
<a name='L318'><i><font color='green'>// 发生意外硬盘中断时,硬盘中断处理程序中调用的默认C 处理函数。在被调用函数指针为空时</font></i>
<a name='L319'><i><font color='green'>// 调用该函数。参见(kernel/system_call.s,241 行)。</font></i>
<a name='L320'><b>void</b> unexpected_hd_interrupt (<b>void</b>)
<a name='L321'><font color='red'>{</font>
<a name='L322'> <a href='../S/73.html#L30' title='Defined at 30 in kernel/printk.c.'>printk</a> ("Unexpected HD interrupt\n\r");
<a name='L323'><font color='red'>}</font>
<a name='L324'>
<a name='L325'><i><font color='green'>//// 读写硬盘失败处理调用函数。</font></i>
<a name='L326'><b>static</b> <b>void</b> <a href='../R/385.html' title='Multiple refered from 4 places.'>bad_rw_intr</a> (<b>void</b>)
<a name='L327'><font color='red'>{</font>
<a name='L328'> <b>if</b> (++<a href='../S/54.html#L116' title='Defined at 116 in kernel/blk_drv/blk.h.'>CURRENT</a>->errors >= <a href='../D/230.html' title='Multiple defined in 2 places.'>MAX_ERRORS</a>) <i><font color='green'>// 如果读扇区时的出错次数大于或等于7 次时,</font></i>
<a name='L329'> <a href='../S/54.html#L136' title='Defined at 136 in kernel/blk_drv/blk.h.'>end_request</a> (0); <i><font color='green'>// 则结束请求并唤醒等待该请求的进程,而且</font></i>
<a name='L330'><i><font color='green'>// 对应缓冲区更新标志复位(没有更新)。</font></i>
<a name='L331'> <b>if</b> (<a href='../S/54.html#L116' title='Defined at 116 in kernel/blk_drv/blk.h.'>CURRENT</a>->errors > <a href='../D/230.html' title='Multiple defined in 2 places.'>MAX_ERRORS</a> / 2) <i><font color='green'>// 如果读一扇区时的出错次数已经大于3 次,</font></i>
<a name='L332'> reset = 1; <i><font color='green'>// 则要求执行复位硬盘控制器操作。</font></i>
<a name='L333'><font color='red'>}</font>
<a name='L334'>
<a name='L335'><i><font color='green'>//// 读操作中断调用函数。将在执行硬盘中断处理程序中被调用。</font></i>
<a name='L336'><b>static</b> <b>void</b> <a href='../R/563.html' title='Multiple refered from 2 places.'>read_intr</a> (<b>void</b>)
<a name='L337'><font color='red'>{</font>
<a name='L338'> <b>if</b> (<a href='../S/56.html#L237' title='Defined at 237 in kernel/blk_drv/hd.c.'>win_result</a> ())
<a name='L339'> <font color='red'>{</font> <i><font color='green'>// 若控制器忙、读写错或命令执行错,</font></i>
<a name='L340'> <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='L341'> <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='L342'> <b>return</b>;
<a name='L343'> <font color='red'>}</font>
<a name='L344'> <a href='../S/56.html#L91' title='Defined at 91 in kernel/blk_drv/hd.c.'>port_read</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>->buffer, 256); <i><font color='green'>// 将数据从数据寄存器口读到请求结构缓冲区。</font></i>
<a name='L345'> <a href='../S/54.html#L116' title='Defined at 116 in kernel/blk_drv/blk.h.'>CURRENT</a>->errors = 0; <i><font color='green'>// 清出错次数。</font></i>
<a name='L346'> <a href='../S/54.html#L116' title='Defined at 116 in kernel/blk_drv/blk.h.'>CURRENT</a>->buffer += 512; <i><font color='green'>// 调整缓冲区指针,指向新的空区。</font></i>
<a name='L347'> <a href='../S/54.html#L116' title='Defined at 116 in kernel/blk_drv/blk.h.'>CURRENT</a>->sector++; <i><font color='green'>// 起始扇区号加1,</font></i>
<a name='L348'> <b>if</b> (--<a href='../S/54.html#L116' title='Defined at 116 in kernel/blk_drv/blk.h.'>CURRENT</a>->nr_sectors)
<a name='L349'> <font color='red'>{</font> <i><font color='green'>// 如果所需读出的扇区数还没有读完,则</font></i>
<a name='L350'> do_hd = &<a href='../S/56.html#L336' title='Defined at 336 in kernel/blk_drv/hd.c.'>read_intr</a>; <i><font color='green'>// 再次置硬盘调用C 函数指针为read_intr()</font></i>
<a name='L351'> <b>return</b>; <i><font color='green'>// 因为硬盘中断处理程序每次调用do_hd 时</font></i>
<a name='L352'> <font color='red'>}</font> <i><font color='green'>// 都会将该函数指针置空。参见system_call.s</font></i>
<a name='L353'> <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='L354'> <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>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -