hd.c ( File view )

  • By 2010-08-31
  • View(s):24
  • Download(s):2
  • Point(s): 1
			/*
* linux/kernel/hd.c
*
* (C) 1991 Linus Torvalds
*/

/*
* This is the low-level hd interrupt support. It traverses the
* request-list, using interrupts to jump between functions. As
* all the functions are called within interrupts, we may not
* sleep. Special care is recommended.
*
* modified by Drew Eckhardt to check nr of hd's from the CMOS.
*/
/*
* 本程序是底层硬盘中断辅助程序。主要用于扫描请求列表,使用中断在函数之间跳转。
* 由于所有的函数都是在中断里调用的,所以这些函数不可以睡眠。请特别注意。
* 由Drew Eckhardt 修改,利用CMOS 信息检测硬盘数。
*/

#include <linux/config.h>	// 内核配置头文件。定义键盘语言和硬盘类型(HD_TYPE)可选项。
#include <linux/sched.h>	// 调度程序头文件,定义了任务结构task_struct、初始任务0 的数据,
// 还有一些有关描述符参数设置和获取的嵌入式汇编函数宏语句。
#include <linux/fs.h>		// 文件系统头文件。定义文件表结构(file,buffer_head,m_inode 等)。
#include <linux/kernel.h>	// 内核头文件。含有一些内核常用函数的原形定义。
#include <linux/hdreg.h>	// 硬盘参数头文件。定义访问硬盘寄存器端口,状态码,分区表等信息。
#include <asm/system.h>		// 系统头文件。定义了设置或修改描述符/中断门等的嵌入式汇编宏。
#include <asm/io.h>		// io 头文件。定义硬件端口输入/输出宏汇编语句。
#include <asm/segment.h>	// 段操作头文件。定义了有关段寄存器操作的嵌入式汇编函数。

#define MAJOR_NR 3		// 硬盘主设备号是3。
#include "blk.h"		// 块设备头文件。定义请求数据结构、块设备数据结构和宏函数等信息。

#define CMOS_READ(addr) ({
 \	// 读CMOS 参数宏函数。
outb_p (0x80 | addr, 0x70);
inb_p (0x71);

}

)
/* Max read/write errors/sector */
#define MAX_ERRORS 7		// 读/写一个扇区时允许的最多出错次数。
#define MAX_HD 2		// 系统支持的最多硬盘数。
     static void recal_intr (void);	// 硬盘中断程序在复位操作时会调用的重新校正函数(287 行)。

     static int recalibrate = 1;	// 重新校正标志。
     static int reset = 1;	// 复位标志。

/*
* This struct defines the HD's and their types.
*/
/* 下面结构定义了硬盘参数及类型 */
// 各字段分别是磁头数、每磁道扇区数、柱面数、写前预补偿柱面号、磁头着陆区柱面号、控制字节。
     struct hd_i_struct
     {

       int head, sect, cyl, wpcom, lzone, ctl;
     
};

#ifdef HD_TYPE			// 如果已经在include/linux/config.h 中定义了HD_TYPE…
struct hd_i_struct hd_info[] =
{

HD_TYPE
};			// 取定义好的参数作为hd_info[]的数据。

#define NR_HD ((sizeof (hd_info))/(sizeof (struct hd_i_struct)))	// 计算硬盘数。
#else // 否则,都设为0 值。
struct hd_i_struct hd_info[] =
{

  {

  0, 0, 0, 0, 0, 0
}
  ,
  {

  0, 0, 0, 0, 0, 0
}

};
static int NR_HD = 0;
#endif

// 定义硬盘分区结构。给出每个分区的物理起始扇区号、分区扇区总数。
// 其中5 的倍数处的项(例如hd[0]和hd[5]等)代表整个硬盘中的参数。
static struct hd_struct
{

  long start_sect;
  long nr_sects;

}

hd[5 * MAX_HD] =
{

  {

  0, 0
}
,
};

// 读端口port,共读nr 字,保存在buf 中。
#define port_read(port,buf,nr) \
__asm__( "cld;rep;insw":: "d" (port), "D" (buf), "c" (nr): "cx", "di")

// 写端口port,共写nr 字,从buf 中取数据。
#define port_write(port,buf,nr) \
__asm__( "cld;rep;outsw":: "d" (port), "S" (buf), "c" (nr): "cx", "si")

extern void hd_interrupt (void);
extern void rd_load (void);

/* This may be used only once, enforced by 'static int callable' */
/* 下面该函数只在初始化时被调用一次。用静态变量callable 作为可调用标志。*/
// 该函数的参数由初始化程序init/main.c 的init 子程序设置为指向0x90080 处,此处存放着setup.s
// 程序从BIOS 取得的2 个硬盘的基本参数表(32 字节)。硬盘参数表信息参见下面列表后的说明。
// 本函数主要功能是读取CMOS 和硬盘参数表信息,用于设置硬盘分区结构hd,并加载RAM 虚拟盘和
// 根文件系统。
int sys_setup (void *BIOS)
{

  static int callable = 1;
  int i, drive;
  unsigned char cmos_disks;
  struct partition *p;
  struct buffer_head *bh;

// 初始化时callable=1,当运行该函数时将其设置为0,使本函数只能执行一次。
  if (!callable)
      return -1;
    callable = 0;
// 如果没有在config.h 中定义硬盘参数,就从0x90080 处读入。
#ifndef HD_TYPE
  for (drive = 0; drive < 2; drive++)
    {

      hd_info[drive].cyl = *(unsigned short *) BIOS;	// 柱面数。
      hd_info[drive].head = *(unsigned char *) (2 + BIOS);	// 磁头数。
      hd_info[drive].wpcom = *(unsigned short *) (5 + BIOS);	// 写前预补偿柱面号。
      hd_info[drive].ctl = *(unsigned char *) (8 + BIOS);	// 控制字节。
      hd_info[drive].lzone = *(unsigned short *) (12 + BIOS);	// 磁头着陆区柱面号。
      hd_info[drive].sect = *(unsigned char *) (14 + BIOS);	// 每磁道扇区数。
      BIOS += 16;		// 每个硬盘的参数表长16 字节,这里BIOS 指向下一个表。
    
}
// setup.s 程序在取BIOS 中的硬盘参数表信息时,如果只有1 个硬盘,就会将对应第2 个硬盘的
// 16 字节全部清零。因此这里只要判断第2 个硬盘柱面数是否为0 就可以知道有没有第2 个硬盘了。
  if (hd_info[1].cyl)
      NR_HD = 2;		// 硬盘数置为2。
  else
    NR_HD = 1;
#endif
// 设置每个硬盘的起始扇区号和扇区总数。其中编号i*5 含义参见本程序后的有关说明。
  for (i = 0; i < NR_HD; i++)
    {

      hd[i * 5].start_sect = 0;	// 硬盘起始扇区号。
      hd[i * 5].nr_sects = hd_info[i].head * hd_info[i].sect * hd_info[i].cyl;	// 硬盘总扇区数。
    
}

/*
We querry CMOS about hard disks : it could be that
we have a SCSI/ESDI/etc controller that is BIOS
compatable with ST-506, and thus showing up in our
BIOS table, but not register compatable, and therefore
not present in CMOS.

Furthurmore, we will assume that our ST-506 drives
<if any> are the primary drives in the system, and
the ones reflected as drive 1 or 2.

The first drive is stored in the high nibble of CMOS
byte 0x12, the second in the low nibble. This will be
either a 4 bit drive type or 0xf indicating use byte 0x19
for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.

Needless to say, a non-zero value means we have
an AT controller hard disk for that drive.


*/
/*
* 我们对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 控制器硬盘兼容的驱动器。
*/

// 这里根据上述原理来检测硬盘到底是否是AT 控制器兼容的。有关CMOS 信息请参见4.2.3.1 节。
  if ((cmos_disks = CMOS_READ (0x12)) & 0xf0)
    if (cmos_disks & 0x0f)
      NR_HD = 2;
    else
      NR_HD = 1;
  else
    NR_HD = 0;
// 若NR_HD=0,则两个硬盘都不是AT 控制器兼容的,硬盘数据结构清零。
// 若NR_HD=1,则将第2 个硬盘的参数清零。
  for (i = NR_HD; i < 2; i++)
    {

      hd[i * 5].start_sect = 0;
      hd[i * 5].nr_sects = 0;
    
}
// 读取每一个硬盘上第1 块数据(第1 个扇区有用),获取其中的分区表信息。
// 首先利用函数bread()读硬盘第1 块数据(fs/buffer.c,267),参数中的0x300 是硬盘的主设备号
// (参见列表后的说明)。然后根据硬盘头1 个扇区位置0x1fe 处的两个字节是否为'55AA'来判断
// 该扇区中位于0x1BE 开始的分区表是否有效。最后将分区表信息放入硬盘分区数据结构hd 中。
  for (drive = 0; drive < NR_HD; drive++)
    {

      if (!(bh = bread (0x300 + drive * 5, 0)))
	{
			// 0x300, 0x305 逻辑设备号。
	  printk ("Unable to read partition table of drive %d\n\r", drive);
	  panic ("");
	
}
      if (bh->b_data[510] != 0x55 || (unsigned char) bh->b_data[511] != 0xAA)
	{
			// 判断硬盘信息有效标志'55AA'。
	  printk ("Bad partition table on drive %d\n\r", drive);
	  panic ("");
	
}
      p = 0x1BE + (void *) bh->b_data;	// 分区表位于硬盘第1 扇区的0x1BE 处。
      for (i = 1; i < 5; i++, p++)
	{

	  hd[i + 5 * drive].start_sect = p->start_sect;
	  hd[i + 5 * drive].nr_sects = p->nr_sects;
	
}
      brelse (bh);		// 释放为存放硬盘块而申请的内存缓冲区页。
    
}
  if (NR_HD)			// 如果有硬盘存在并且已读入分区表,则打印分区表正常信息。
    printk ("Partition table%s ok.\n\r", (NR_HD > 1) ? "s" : "");
  rd_load ();			// 加载(创建)RAMDISK(kernel/blk_drv/ramdisk.c,71)。
  mount_root ();		// 安装根文件系统(fs/super.c,242)。
  return (0);

}

//// 判断并循环等待驱动器就绪。
// 读硬盘控制器状态寄存器端口HD_STATUS(0x1f7),并循环检测驱动器就绪比特位和控制器忙位。
static int controller_ready (void)
{

  int retries = 10000;

  while (--retries && (inb_p (HD_STATUS) & 0xc0) != 0x40);
    return (retries);		// 返回等待循环的次数。

}

//// 检测硬盘执行命令后的状态。(win_表示温切斯特硬盘的缩写)
// 读取状态寄存器中的命令执行结果状态。返回0 表示正常,1 出错。如果执行命令错,
// 则再读错误寄存器HD_ERROR(0x1f1)。
static int win_result (void)
{

  int i = inb_p (HD_STATUS);	// 取状态信息。

  if ((i & (BUSY_STAT | READY_STAT | W
...
...
(Not finished, please download and read the complete file)
			
...
Expand> <Close

Want complete source code? Download it here

Point(s): 1

Download
0 lines left, continue to read
Sponsored links

File list

Tips: You can preview the content of files by clicking file names^_^
Name Size Date
linux0.00 B0% 04-10-07
<boot>0.00 B04-10-07 15:01
bootsect.s12.49 kB08-01-04 21:38
head.s13.22 kB08-01-04 21:38
setup.s12.42 kB08-01-04 21:38
<fs>0.00 B04-10-07 15:01
bitmap.c8.46 kB02-09-04 13:12
block_dev.c3.95 kB02-09-04 13:12
buffer.c17.71 kB02-09-04 13:12
char_dev.c4.09 kB02-09-04 13:12
exec.c18.90 kB02-09-04 13:12
fcntl.c3.33 kB02-09-04 13:12
file_dev.c4.82 kB02-09-04 13:12
file_table.c209.00 B02-09-04 13:12
inode.c14.92 kB02-09-04 13:12
ioctl.c1.94 kB02-09-04 13:12
Makefile6.80 kB08-01-04 21:45
namei.c37.20 kB02-09-04 13:12
open.c10.00 kB02-09-04 13:12
pipe.c5.42 kB02-09-04 13:12
read_write.c5.86 kB02-09-04 13:12
stat.c2.69 kB02-09-04 13:12
super.c13.57 kB02-09-04 13:12
truncate.c2.46 kB02-09-04 13:12
<include>0.00 B04-10-07 15:01
a.out.h8.22 kB02-09-04 13:14
<asm>0.00 B04-10-07 15:01
io.h772.00 B02-09-04 13:14
memory.h1.03 kB08-01-04 22:13
segment.h2.50 kB02-09-04 13:14
system.h4.08 kB02-09-04 13:14
const.h589.00 B02-09-04 13:14
ctype.h1.68 kB02-09-04 13:14
errno.h2.30 kB02-09-04 13:14
fcntl.h3.30 kB02-09-04 13:14
<linux>0.00 B04-10-07 15:01
config.h2.16 kB02-09-04 13:14
fs.h9.72 kB02-09-04 13:14
hdreg.h2.94 kB02-09-04 13:14
head.h760.00 B02-09-04 13:14
kernel.h1.44 kB02-09-04 13:14
mm.h473.00 B02-09-04 13:14
sched.h13.25 kB02-09-04 13:14
sys.h5.41 kB02-09-04 13:14
tty.h3.93 kB02-09-04 13:14
signal.h4.01 kB02-09-04 13:14
stdarg.h1.77 kB02-09-04 13:14
stddef.h378.00 B02-09-04 13:14
string.h21.75 kB02-09-04 13:14
<sys>0.00 B04-10-07 15:01
stat.h2.37 kB02-09-04 13:14
times.h377.00 B02-09-04 13:14
types.h1.10 kB02-09-04 13:14
utsname.h423.00 B02-09-04 13:14
wait.h1.48 kB02-09-04 13:14
termios.h13.58 kB02-09-04 13:14
time.h1.81 kB02-09-04 13:14
unistd.h9.21 kB02-09-04 13:14
utime.h392.00 B02-09-04 13:14
<init>0.00 B04-10-07 15:01
main.c12.52 kB02-09-04 13:12
<kernel>0.00 B04-10-07 15:01
asm.s5.10 kB08-01-04 22:48
<blk_drv>0.00 B04-10-07 15:01
blk.h5.69 kB02-09-04 13:14
floppy.c23.49 kB02-09-04 13:12
hd.c17.14 kB02-09-04 13:12
ll_rw_blk.c7.59 kB02-09-04 13:12
Makefile4.25 kB08-01-04 22:53
ramdisk.c6.13 kB02-09-04 13:12
<chr_drv>0.00 B04-10-07 15:01
console.c30.91 kB02-09-04 13:12
keyboard.S21.04 kB08-01-04 22:59
Makefile4.81 kB08-01-04 22:59
rs_io.s5.75 kB08-01-04 22:59
serial.c2.91 kB02-09-04 13:12
tty_io.c18.40 kB02-09-04 13:12
tty_ioctl.c10.70 kB02-09-04 13:12
exit.c8.08 kB02-09-04 13:12
fork.c6.78 kB15-07-07 22:10
<math>0.00 B04-10-07 15:01
Makefile3.21 kB08-01-04 23:01
math_emulate.c2.08 kB02-09-04 13:12
mktime.c2.72 kB02-09-04 13:12
panic.c952.00 B02-09-04 13:12
printk.c1.75 kB02-09-04 13:12
sched.c18.57 kB16-07-07 21:23
signal.c5.61 kB02-09-04 13:12
sys.c7.62 kB02-09-04 13:12
system_call.s12.53 kB08-01-04 22:48
traps.c8.29 kB04-10-07 14:57
vsprintf.c9.96 kB02-09-04 13:12
<lib>0.00 B04-10-07 15:01
close.c397.00 B02-09-04 13:12
ctype.c1.72 kB02-09-04 13:12
dup.c401.00 B02-09-04 13:12
errno.c66.00 B02-09-04 13:12
execve.c607.00 B02-09-04 13:12
Makefile4.83 kB08-01-04 22:30
malloc.c13.50 kB02-09-04 13:12
open.c1.22 kB02-09-04 13:12
setsid.c382.00 B02-09-04 13:12
string.c199.00 B02-09-04 13:12
wait.c774.00 B02-09-04 13:12
write.c545.00 B02-09-04 13:12
_exit.c616.00 B02-09-04 13:12
Makefile8.58 kB08-01-04 22:21
<mm>0.00 B04-10-07 15:01
Makefile2.91 kB08-01-04 22:34
memory.c25.10 kB02-09-04 13:12
page.s842.00 B08-01-04 22:34
<tools>0.00 B04-10-07 15:01
build.c8.12 kB02-09-04 13:12
...
Sponsored links

hd.c (286.77 kB)

Need 1 point
Your Point(s)

Your Point isn't enough.

Get point immediately by PayPal

More(Debit card / Credit card / PayPal Credit / Online Banking)

Submit your source codes. Get more point

LOGIN

Don't have an account? Register now
Need any help?
Mail to: support@codeforge.com

切换到中文版?

CodeForge Chinese Version
CodeForge English Version

Where are you going?

^_^"Oops ...

Sorry!This guy is mysterious, its blog hasn't been opened, try another, please!
OK

Warm tip!

CodeForge to FavoriteFavorite by Ctrl+D