#ifndef _BLK_H
#define _BLK_H

#define NR_BLK_DEV 7		// 豸
/*
* NR_REQUEST is the number of entries in the request-queue.
* NOTE that writes may use only the low 2/3 of these: reads
* take precedence.
*
* 32 seems to be a reasonable number: enough to get some benefit
* from the elevator-mechanism, but not so much as to lock a lot of
* buffers when they are in the queue. 64 seems to be too many (easily
* long pauses in reading when heavy writing/syncing is going on)
*/
/*
* 涨NR_REQUEST 
* ע⣬ʹЩͶ˵2/3ȴ
*
* 32 һ֣Ѿ㹻ӵ㷨лúô
* ڶжסʱֲԵǺܴ64 Ϳ
* ȥ̫ˣд/ͬʱʱͣ
*/
#define NR_REQUEST 32

/*
* Ok, this is an expanded form so that we can use the same
* request for paging requests when that is implemented. In
* paging, 'bh' is NULL, and 'waiting' is used to wait for
* read/write completion.
*/
/*
* OKrequest ṹһչʽʵԺǾͿڷҳ
* ʹͬrequest ṹڷҳУ'bh'NULL'waiting'ڵȴ/дɡ
*/
// Ľṹdev=-1ʾûбʹá
struct request
{
  int dev;			/* -1 if no request */// ʹõ豸š
  int cmd;			/* READ or WRITE */// (READ WRITE)
  int errors;			//ʱĴ
  unsigned long sector;		// ʼ(1 =2 )
  unsigned long nr_sectors;	// /д
  char *buffer;			// ݻ
  struct task_struct *waiting;	// ȴִɵĵط
  struct buffer_head *bh;	// ͷָ(include/linux/fs.h,68)
  struct request *next;		// ָһ
};

/*
* This is used in the elevator algorithm: Note that
* reads always go before writes. This is natural: reads
* are much more time-critical than writes.
*/
/*
* Ķڵ㷨עд֮ǰС
* ǺȻģʱҪҪдϸöࡣ
*/
#define IN_ORDER(s1,s2) \
((s1)->cmd<(s2)->cmd || (s1)->cmd==(s2)->cmd && \
((s1)->dev < (s2)->dev || ((s1)->dev == (s2)->dev && \
(s1)->sector < (s2)->sector)))

// 豸ṹ
struct blk_dev_struct
{
  void (*request_fn) (void);	// ĺָ롣
  struct request *current_request;	// Ϣṹ
};

extern struct blk_dev_struct blk_dev[NR_BLK_DEV];	// 豸飬ÿֿ豸ռһ
extern struct request request[NR_REQUEST];	// 顣
extern struct task_struct *wait_for_request;	// ȴṹ

#ifdef MAJOR_NR			// 豸š

/*
* Add entries as needed. Currently the only block devices
* supported are hard-disks and floppies.
*/
/*
* ҪʱĿĿǰ豸֧Ӳ̺̣̣
*/

#if (MAJOR_NR == 1)		// RAM ̵豸1Ķڴ豸ҲΪ1
/* ram disk *//* RAM ̣ڴ̣ */
#define DEVICE_NAME "ramdisk"	// 豸ramdisk
#define DEVICE_REQUEST do_rd_request	// 豸do_rd_request()
#define DEVICE_NR(device) ((device) & 7)	// 豸(0--7)
#define DEVICE_ON(device)	// 豸뿪͹رա
#define DEVICE_OFF(device)	// ر豸

#elif (MAJOR_NR == 2)		// 豸2
/* floppy */
#define DEVICE_NAME "floppy"	// 豸floppy
#define DEVICE_INTR do_floppy	// 豸жϴdo_floppy()
#define DEVICE_REQUEST do_fd_request	// 豸do_fd_request()
#define DEVICE_NR(device) ((device) & 3)	// 豸ţ0--3
#define DEVICE_ON(device) floppy_on(DEVICE_NR(device))	// 豸floppyon()
#define DEVICE_OFF(device) floppy_off(DEVICE_NR(device))	// ر豸floppyoff()

#elif (MAJOR_NR == 3)		// Ӳ豸3
/* harddisk */
#define DEVICE_NAME "harddisk"	// Ӳharddisk
#define DEVICE_INTR do_hd	// 豸жϴdo_hd()
#define DEVICE_REQUEST do_hd_request	// 豸do_hd_request()
#define DEVICE_NR(device) (MINOR(device)/5)	// 豸ţ0--1ÿӲ̿4 
#define DEVICE_ON(device)	// Ӳһֱڹ뿪͹رա
#define DEVICE_OFF(device)

#elif
/* unknown blk device *//* δ֪豸 */
#error "unknown blk device"

#endif

#define CURRENT (blk_dev[MAJOR_NR].current_request)	// CURRENT Ϊָ豸ŵĵǰṹ
#define CURRENT_DEV DEVICE_NR(CURRENT->dev)	// CURRENT_DEV ΪCURRENT 豸š

#ifdef DEVICE_INTR
void (*DEVICE_INTR) (void) = NULL;
#endif
static void (DEVICE_REQUEST) (void);

// ͷĻ
extern inline void
unlock_buffer (struct buffer_head *bh)
{
  if (!bh->b_lock)		// ָĻbh ûбʾϢ
    printk (DEVICE_NAME ": free buffer being unlocked\n");
  bh->b_lock = 0;		// 򽫸û
  wake_up (&bh->b_wait);	// ѵȴûĽ̡
}

// 
extern inline void
end_request (int uptodate)
{
  DEVICE_OFF (CURRENT->dev);	// ر豸
  if (CURRENT->bh)
    {				// CURRENT Ϊָ豸ŵĵǰṹ
      CURRENT->bh->b_uptodate = uptodate;	// ø±־
      unlock_buffer (CURRENT->bh);	// 
    }
  if (!uptodate)
    {				// ±־Ϊ0 ʾ豸Ϣ
      printk (DEVICE_NAME " I/O error\n\r");
      printk ("dev %04x, block %d\n\r", CURRENT->dev, CURRENT->bh->b_blocknr);
    }
  wake_up (&CURRENT->waiting);	// ѵȴĽ̡
  wake_up (&wait_for_request);	// ѵȴĽ̡
  CURRENT->dev = -1;		// ͷŸ
  CURRENT = CURRENT->next;	// ɾ
}

// ʼꡣ
#define INIT_REQUEST \
repeat: \
if (!CURRENT) \			// ǰṹָΪnull 򷵻ء
return;
if (MAJOR (CURRENT->dev) != MAJOR_NR)
  \				// ǰ豸豸Ų
    panic (DEVICE_NAME ": request list destroyed");
if (CURRENT->bh)
  {
    if (!CURRENT->bh->b_lock)
      \				// ڽʱû
	panic (DEVICE_NAME ": block not locked");
  }

#endif

#endif
