📄 56.html
字号:
<a name='L99'><b>extern</b> <b>void</b> <a href='../S/59.html#L103' title='Defined at 103 in kernel/blk_drv/ramdisk.c.'>rd_load</a> (<b>void</b>);
<a name='L100'>
<a name='L101'><i><font color='green'>/* This may be used only once, enforced by 'static int callable' */</font></i>
<a name='L102'><i><font color='green'>/* 下面该函数只在初始化时被调用一次。用静态变量callable 作为可调用标志。*/</font></i>
<a name='L103'><i><font color='green'>// 该函数的参数由初始化程序init/main.c 的init 子程序设置为指向0x90080 处,此处存放着setup.s</font></i>
<a name='L104'><i><font color='green'>// 程序从BIOS 取得的2 个硬盘的基本参数表(32 字节)。硬盘参数表信息参见下面列表后的说明。</font></i>
<a name='L105'><i><font color='green'>// 本函数主要功能是读取CMOS 和硬盘参数表信息,用于设置硬盘分区结构hd,并加载RAM 虚拟盘和</font></i>
<a name='L106'><i><font color='green'>// 根文件系统。</font></i>
<a name='L107'><b>int</b> <a href='../R/678.html' title='Multiple refered from 2 places.'>sys_setup</a> (<b>void</b> *BIOS)
<a name='L108'><font color='red'>{</font>
<a name='L109'> <b>static</b> <b>int</b> callable = 1;
<a name='L110'> <b>int</b> <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>, drive;
<a name='L111'> <b>unsigned</b> <b>char</b> cmos_disks;
<a name='L112'> <b>struct</b> partition *p;
<a name='L113'> <b>struct</b> buffer_head *bh;
<a name='L114'>
<a name='L115'><i><font color='green'>// 初始化时callable=1,当运行该函数时将其设置为0,使本函数只能执行一次。</font></i>
<a name='L116'> <b>if</b> (!callable)
<a name='L117'> <b>return</b> -1;
<a name='L118'> callable = 0;
<a name='L119'><i><font color='green'>// 如果没有在config.h 中定义硬盘参数,就从0x90080 处读入。</font></i>
<a name='L120'><font color='darkred'>#ifndef</font> HD_TYPE
<a name='L121'> <b>for</b> (drive = 0; drive < 2; drive++)
<a name='L122'> <font color='red'>{</font>
<a name='L123'> hd_info[drive].cyl = *(<b>unsigned</b> <b>short</b> *) BIOS; <i><font color='green'>// 柱面数。</font></i>
<a name='L124'> hd_info[drive].head = *(<b>unsigned</b> <b>char</b> *) (2 + BIOS); <i><font color='green'>// 磁头数。</font></i>
<a name='L125'> hd_info[drive].wpcom = *(<b>unsigned</b> <b>short</b> *) (5 + BIOS); <i><font color='green'>// 写前预补偿柱面号。</font></i>
<a name='L126'> hd_info[drive].ctl = *(<b>unsigned</b> <b>char</b> *) (8 + BIOS); <i><font color='green'>// 控制字节。</font></i>
<a name='L127'> hd_info[drive].lzone = *(<b>unsigned</b> <b>short</b> *) (12 + BIOS); <i><font color='green'>// 磁头着陆区柱面号。</font></i>
<a name='L128'> hd_info[drive].sect = *(<b>unsigned</b> <b>char</b> *) (14 + BIOS); <i><font color='green'>// 每磁道扇区数。</font></i>
<a name='L129'> BIOS += 16; <i><font color='green'>// 每个硬盘的参数表长16 字节,这里BIOS 指向下一个表。</font></i>
<a name='L130'> <font color='red'>}</font>
<a name='L131'><i><font color='green'>// setup.s 程序在取BIOS 中的硬盘参数表信息时,如果只有1 个硬盘,就会将对应第2 个硬盘的</font></i>
<a name='L132'><i><font color='green'>// 16 字节全部清零。因此这里只要判断第2 个硬盘柱面数是否为0 就可以知道有没有第2 个硬盘了。</font></i>
<a name='L133'> <b>if</b> (hd_info[1].cyl)
<a name='L134'> <a href='../S/56.html#L63' title='Defined at 63 in kernel/blk_drv/hd.c.'>NR_HD</a> = 2; <i><font color='green'>// 硬盘数置为2。</font></i>
<a name='L135'> <b>else</b>
<a name='L136'> <a href='../S/56.html#L63' title='Defined at 63 in kernel/blk_drv/hd.c.'>NR_HD</a> = 1;
<a name='L137'><font color='darkred'>#endif</font>
<a name='L138'><i><font color='green'>// 设置每个硬盘的起始扇区号和扇区总数。其中编号i*5 含义参见本程序后的有关说明。</font></i>
<a name='L139'> <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> < <a href='../S/56.html#L63' title='Defined at 63 in kernel/blk_drv/hd.c.'>NR_HD</a>; <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>++)
<a name='L140'> <font color='red'>{</font>
<a name='L141'> hd[<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> * 5].start_sect = 0; <i><font color='green'>// 硬盘起始扇区号。</font></i>
<a name='L142'> hd[<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> * 5].nr_sects = hd_info[<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>].head * hd_info[<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>].sect * hd_info[<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>].cyl; <i><font color='green'>// 硬盘总扇区数。</font></i>
<a name='L143'> <font color='red'>}</font>
<a name='L144'>
<a name='L145'><i><font color='green'>/*</font></i>
<a name='L146'><i><font color='green'>We querry CMOS about hard disks : it could be that</font></i>
<a name='L147'><i><font color='green'>we have a SCSI/ESDI/etc controller that is BIOS</font></i>
<a name='L148'><i><font color='green'>compatable with ST-506, and thus showing up in our</font></i>
<a name='L149'><i><font color='green'>BIOS table, but not register compatable, and therefore</font></i>
<a name='L150'><i><font color='green'>not present in CMOS.</font></i>
<a name='L151'><i><font color='green'></font></i>
<a name='L152'><i><font color='green'>Furthurmore, we will assume that our ST-506 drives</font></i>
<a name='L153'><i><font color='green'><if any> are the primary drives in the system, and</font></i>
<a name='L154'><i><font color='green'>the ones reflected as drive 1 or 2.</font></i>
<a name='L155'><i><font color='green'></font></i>
<a name='L156'><i><font color='green'>The first drive is stored in the high nibble of CMOS</font></i>
<a name='L157'><i><font color='green'>byte 0x12, the second in the low nibble. This will be</font></i>
<a name='L158'><i><font color='green'>either a 4 bit drive type or 0xf indicating use byte 0x19</font></i>
<a name='L159'><i><font color='green'>for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.</font></i>
<a name='L160'><i><font color='green'></font></i>
<a name='L161'><i><font color='green'>Needless to say, a non-zero value means we have</font></i>
<a name='L162'><i><font color='green'>an AT controller hard disk for that drive.</font></i>
<a name='L163'><i><font color='green'></font></i>
<a name='L164'><i><font color='green'></font></i>
<a name='L165'><i><font color='green'>*/</font></i>
<a name='L166'><i><font color='green'>/*</font></i>
<a name='L167'><i><font color='green'>* 我们对CMOS 有关硬盘的信息有些怀疑:可能会出现这样的情况,我们有一块SCSI/ESDI/等的</font></i>
<a name='L168'><i><font color='green'>* 控制器,它是以ST-506 方式与BIOS 兼容的,因而会出现在我们的BIOS 参数表中,但却又不</font></i>
<a name='L169'><i><font color='green'>* 是寄存器兼容的,因此这些参数在CMOS 中又不存在。</font></i>
<a name='L170'><i><font color='green'>* 另外,我们假设ST-506 驱动器(如果有的话)是系统中的基本驱动器,也即以驱动器1 或2</font></i>
<a name='L171'><i><font color='green'>* 出现的驱动器。</font></i>
<a name='L172'><i><font color='green'>* 第1 个驱动器参数存放在CMOS 字节0x12 的高半字节中,第2 个存放在低半字节中。该4 位字节</font></i>
<a name='L173'><i><font color='green'>* 信息可以是驱动器类型,也可能仅是0xf。0xf 表示使用CMOS 中0x19 字节作为驱动器1 的8 位</font></i>
<a name='L174'><i><font color='green'>* 类型字节,使用CMOS 中0x1A 字节作为驱动器2 的类型字节。</font></i>
<a name='L175'><i><font color='green'>* 总之,一个非零值意味着我们有一个AT 控制器硬盘兼容的驱动器。</font></i>
<a name='L176'><i><font color='green'>*/</font></i>
<a name='L177'>
<a name='L178'><i><font color='green'>// 这里根据上述原理来检测硬盘到底是否是AT 控制器兼容的。有关CMOS 信息请参见4.2.3.1 节。</font></i>
<a name='L179'> <b>if</b> ((cmos_disks = <a href='../S/56.html#L34' title='Defined at 34 in kernel/blk_drv/hd.c.'>CMOS_READ</a> (0x12)) & 0xf0)
<a name='L180'> <b>if</b> (cmos_disks & 0x0f)
<a name='L181'> <a href='../S/56.html#L63' title='Defined at 63 in kernel/blk_drv/hd.c.'>NR_HD</a> = 2;
<a name='L182'> <b>else</b>
<a name='L183'> <a href='../S/56.html#L63' title='Defined at 63 in kernel/blk_drv/hd.c.'>NR_HD</a> = 1;
<a name='L184'> <b>else</b>
<a name='L185'> <a href='../S/56.html#L63' title='Defined at 63 in kernel/blk_drv/hd.c.'>NR_HD</a> = 0;
<a name='L186'><i><font color='green'>// 若NR_HD=0,则两个硬盘都不是AT 控制器兼容的,硬盘数据结构清零。</font></i>
<a name='L187'><i><font color='green'>// 若NR_HD=1,则将第2 个硬盘的参数清零。</font></i>
<a name='L188'> <b>for</b> (<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> = <a href='../S/56.html#L63' title='Defined at 63 in kernel/blk_drv/hd.c.'>NR_HD</a>; <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> < 2; <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>++)
<a name='L189'> <font color='red'>{</font>
<a name='L190'> hd[<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> * 5].start_sect = 0;
<a name='L191'> hd[<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> * 5].nr_sects = 0;
<a name='L192'> <font color='red'>}</font>
<a name='L193'><i><font color='green'>// 读取每一个硬盘上第1 块数据(第1 个扇区有用),获取其中的分区表信息。</font></i>
<a name='L194'><i><font color='green'>// 首先利用函数bread()读硬盘第1 块数据(fs/buffer.c,267),参数中的0x300 是硬盘的主设备号</font></i>
<a name='L195'><i><font color='green'>// (参见列表后的说明)。然后根据硬盘头1 个扇区位置0x1fe 处的两个字节是否为'55AA'来判断</font></i>
<a name='L196'><i><font color='green'>// 该扇区中位于0x1BE 开始的分区表是否有效。最后将分区表信息放入硬盘分区数据结构hd 中。</font></i>
<a name='L197'> <b>for</b> (drive = 0; drive < <a href='../S/56.html#L63' title='Defined at 63 in kernel/blk_drv/hd.c.'>NR_HD</a>; drive++)
<a name='L198'> <font color='red'>{</font>
<a name='L199'> <b>if</b> (!(bh = <a href='../S/6.html#L397' title='Defined at 397 in fs/buffer.c.'>bread</a> (0x300 + drive * 5, 0)))
<a name='L200'> <font color='red'>{</font> <i><font color='green'>// 0x300, 0x305 逻辑设备号。</font></i>
<a name='L201'> <a href='../S/73.html#L30' title='Defined at 30 in kernel/printk.c.'>printk</a> ("Unable to read partition table of drive %d\n\r", drive);
<a name='L202'> <a href='../S/72.html#L24' title='Defined at 24 in kernel/panic.c.'>panic</a> ("");
<a name='L203'> <font color='red'>}</font>
<a name='L204'> <b>if</b> (bh->b_data[510] != 0x55 || (<b>unsigned</b> <b>char</b>) bh->b_data[511] != 0xAA)
<a name='L205'> <font color='red'>{</font> <i><font color='green'>// 判断硬盘信息有效标志'55AA'。</font></i>
<a name='L206'> <a href='../S/73.html#L30' title='Defined at 30 in kernel/printk.c.'>printk</a> ("Bad partition table on drive %d\n\r", drive);
<a name='L207'> <a href='../S/72.html#L24' title='Defined at 24 in kernel/panic.c.'>panic</a> ("");
<a name='L208'> <font color='red'>}</font>
<a name='L209'> p = 0x1BE + (<b>void</b> *) bh->b_data; <i><font color='green'>// 分区表位于硬盘第1 扇区的0x1BE 处。</font></i>
<a name='L210'> <b>for</b> (<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> = 1; <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> < 5; <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>++, p++)
<a name='L211'> <font color='red'>{</font>
<a name='L212'> hd[<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> + 5 * drive].start_sect = p->start_sect;
<a name='L213'> hd[<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> + 5 * drive].nr_sects = p->nr_sects;
<a name='L214'> <font color='red'>}</font>
<a name='L215'> <a href='../S/6.html#L377' title='Defined at 377 in fs/buffer.c.'>brelse</a> (bh); <i><font color='green'>// 释放为存放硬盘块而申请的内存缓冲区页。</font></i>
<a name='L216'> <font color='red'>}</font>
<a name='L217'> <b>if</b> (<a href='../S/56.html#L63' title='Defined at 63 in kernel/blk_drv/hd.c.'>NR_HD</a>) <i><font color='green'>// 如果有硬盘存在并且已读入分区表,则打印分区表正常信息。</font></i>
<a name='L218'> <a href='../S/73.html#L30' title='Defined at 30 in kernel/printk.c.'>printk</a> ("Partition table%s ok.\n\r", (<a href='../S/56.html#L63' title='Defined at 63 in kernel/blk_drv/hd.c.'>NR_HD</a> > 1) ? "s" : "");
<a name='L219'> <a href='../S/59.html#L103' title='Defined at 103 in kernel/blk_drv/ramdisk.c.'>rd_load</a> (); <i><font color='green'>// 加载(创建)RAMDISK(kernel/blk_drv/ramdisk.c,71)。</font></i>
<a name='L220'> <a href='../S/19.html#L354' title='Defined at 354 in fs/super.c.'>mount_root</a> (); <i><font color='green'>// 安装根文件系统(fs/super.c,242)。</font></i>
<a name='L221'> <b>return</b> (0);
<a name='L222'><font color='red'>}</font>
<a name='L223'>
<a name='L224'><i><font color='green'>//// 判断并循环等待驱动器就绪。</font></i>
<a name='L225'><i><font color='green'>// 读硬盘控制器状态寄存器端口HD_STATUS(0x1f7),并循环检测驱动器就绪比特位和控制器忙位。</font></i>
<a name='L226'><b>static</b> <b>int</b> <a href='../S/56.html#L262' title='Refered from 262 in kernel/blk_drv/hd.c.'>controller_ready</a> (<b>void</b>)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -