/*
* linux/kernel/blk_drv/ramdisk.c
*
* Written by Theodore Ts'o, 12/2/91
*/
/* Theodore Ts'o ƣ12/2/91
*/
// Theodore Ts'o (Ted Ts'o)linux еLinux 緶ΧڵҲܴ
// ͣLinux ϵͳʱͻżΪlinux ķչṩmaillist
// ڱ޵linux ftp վ㣨tsx-11.mit.eduȻΪlinux û
// ṩlinux ֮һʵext2 ļϵͳļϵͳѳΪ
// linux ʵϵļϵͳ׼Ƴext3 ļϵͳļϵͳ
// ȶԺͷЧʡΪƳ磬97 ڣ2002 5 £linuxjournal ڿΪ
// ˷˲ɷáĿǰΪIBM linux ĹйLSB
// (Linux Standard Base)ȷĹ(ҳhttp://thunk.org/tytso/)

#include <string.h>		// ַͷļҪһЩйַǶ뺯

#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 <asm/system.h>		// ϵͳͷļû޸/жŵȵǶʽꡣ
#include <asm/segment.h>	// βͷļйضμĴǶʽຯ
#include <asm/memory.h>		// ڴ濽ͷļmemcpy()Ƕʽ꺯

#define MAJOR_NR 1		// ڴ豸1
#include "blk.h"

char *rd_start;			// ڴеʼλá52 гʼrd_init()
// ȷμ(init/main.c,124)дrd_ramdisk_
int rd_length = 0;		// ռڴСֽڣ

// ִ(ramdisk)дṹdo_hd_request()(kernel/blk_drv/hd.c,294)
void
do_rd_request (void)
{
  int len;
  char *addr;

  INIT_REQUEST;			// ĺϷ(μkernel/blk_drv/blk.h,127)
// ȡramdisk ʼӦڴʼλúڴ泤ȡ
// sector << 9 ʾsector * 512CURRENT Ϊ(blk_dev[MAJOR_NR].current_request)
  addr = rd_start + (CURRENT->sector << 9);
  len = CURRENT->nr_sectors << 9;
// 豸ŲΪ1 ߶Ӧڴʼλ>ĩβ󣬲תrepeat 
// 28 еINIT_REQUEST ڿʼ
  if ((MINOR (CURRENT->dev) != 1) || (addr + len > rd_start + rd_length))
    {
      end_request (0);
      goto repeat;
    }
// д(WRITE)лݸƵaddr Ϊlen ֽڡ
  if (CURRENT->cmd == WRITE)
    {
      (void) memcpy (addr, CURRENT->buffer, len);
// Ƕ(READ)addr ʼݸƵлУΪlen ֽڡ
    }
  else if (CURRENT->cmd == READ)
    {
      (void) memcpy (CURRENT->buffer, addr, len);
// ʾڣ
    }
  else
    panic ("unknown ramdisk-command");
// ɹø±־豸һ
  end_request (1);
  goto repeat;
}

/*
* Returns amount of memory which needs to be reserved.
*/
/* ڴramdisk ڴ */
// ̳ʼȷڴеʼַȡ㡣
long
rd_init (long mem_start, int length)
{
  int i;
  char *cp;

  blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;	// do_rd_request()
  rd_start = (char *) mem_start;
  rd_length = length;
  cp = rd_start;
  for (i = 0; i < length; i++)
    *cp++ = '\0';
  return (length);
}

/*
* If the root device is the ram disk, try to load it.
* In order to do this, the root device is originally set to the
* floppy, and we later change it to be ram disk.
*/
/*
* ļϵͳ豸(root device)ramdisk ĻԼroot device ԭָ
* ̵ģǽĳָramdisk
*/
//// ظļϵͳramdisk
void
rd_load (void)
{
  struct buffer_head *bh;
  struct super_block s;
  int block = 256;		/* Start at block 256 */
  int i = 1;
  int nblocks;
  char *cp;			/* Move pointer */

  if (!rd_length)		// ramdisk ĳΪ㣬˳
    return;
  printk ("Ram disk: %d bytes, starting at 0x%x\n", rd_length, (int) rd_start);	// ʾramdisk ĴСԼڴʼλá
  if (MAJOR (ROOT_DEV) != 2)	// ʱļ豸̣˳
    return;
// ̿256+1,256,256+2breada()ڶȡָݿ飬ҪĿ飬Ȼ󷵻
// ݿĻָ롣NULLʾݿ鲻ɶ(fs/buffer.c,322)
// block+1 ָϵĳ顣
  bh = breada (ROOT_DEV, block + 1, block, block + 2, -1);
  if (!bh)
    {
      printk ("Disk error while looking for ramdisk!\n");
      return;
    }
// s ָ򻺳еĴ̳顣(d_super_block гṹ)
  *((struct d_super_block *) &s) = *((struct d_super_block *) bh->b_data);
  brelse (bh);			// [?? Ϊʲôûиƾͷأ]
  if (s.s_magic != SUPER_MAGIC)	// ħԣ˵minix ļϵͳ
/* No ram disk image present, assume normal floppy boot */
/* ûramdisk ӳļ˳ִͨ */
    return;
//  = ߼() * 2^(ÿοĴη)
// ݿڴɵĿܼأʾϢءʾ
// ݿϢ
  nblocks = s.s_nzones << s.s_log_zone_size;
  if (nblocks > (rd_length >> BLOCK_SIZE_BITS))
    {
      printk ("Ram disk image too big! (%d blocks, %d avail)\n",
	      nblocks, rd_length >> BLOCK_SIZE_BITS);
      return;
    }
  printk ("Loading %d bytes into ram disk... 0000k",
	  nblocks << BLOCK_SIZE_BITS);
// cp ָʼȻ󽫴ϵĸļϵͳӳļƵϡ
  cp = rd_start;
  while (nblocks)
    {
      if (nblocks > 2)		// ȡĿ3 óǰԤʽݿ顣
	bh = breada (ROOT_DEV, block, block + 1, block + 2, -1);
      else			// ͵ȡ
	bh = bread (ROOT_DEV, block);
      if (!bh)
	{
	  printk ("I/O error on block %d, aborting load\n", block);
	  return;
	}
      (void) memcpy (cp, bh->b_data, BLOCK_SIZE);	// еݸƵcp 
      brelse (bh);		// ͷŻ
      printk ("\010\010\010\010\010%4dk", i);	// ӡؿֵ
      cp += BLOCK_SIZE;		// ָǰơ
      block++;
      nblocks--;
      i++;
    }
  printk ("\010\010\010\010\010done \n");
  ROOT_DEV = 0x0101;		// ޸ROOT_DEV ʹָramdisk
}
