/*
* This file has definitions for some important file table
* structures etc.
*/
/*
* ļĳЩҪļṹĶȡ
*/

#ifndef _FS_H
#define _FS_H

#include <sys/types.h>		// ͷļ˻ϵͳ͡

/* devices are as follows: (same as minix, so we can use the minix
* file system. These are major numbers.)
*
* 0 - unused (nodev)
* 1 - /dev/mem
* 2 - /dev/fd
* 3 - /dev/hd
* 4 - /dev/ttyx
* 5 - /dev/tty
* 6 - /dev/lp
* 7 - unnamed pipes
*/
/*
* ϵͳ豸£minix ϵͳһǿʹminix 
* ļϵͳЩ豸š
*
* 0 - ûõnodev
* 1 - /dev/mem ڴ豸
* 2 - /dev/fd 豸
* 3 - /dev/hd Ӳ豸
* 4 - /dev/ttyx tty ն豸
* 5 - /dev/tty tty ն豸
* 6 - /dev/lp ӡ豸
* 7 - unnamed pipes ûĹܵ
*/

#define IS_SEEKABLE(x) ((x)>=1 && (x)<=3)	// ǷǿѰҶλ豸

#define READ 0
#define WRITE 1
#define READA 2			/* read-ahead - don't pause */
#define WRITEA 3		/* "write-ahead" - silly, but somewhat useful */

void buffer_init (long buffer_end);

#define MAJOR(a) (((unsigned)(a))>>8)	// ȡֽڣ豸ţ
#define MINOR(a) ((a)&0xff)	// ȡֽڣ豸ţ

#define NAME_LEN 14		// ֳֵ
#define ROOT_INO 1		// i ڵ㡣

#define I_MAP_SLOTS 8		// i ڵλͼ
#define Z_MAP_SLOTS 8		// ߼飨ο飩λͼ
#define SUPER_MAGIC 0x137F	// ļϵͳħ

#define NR_OPEN 20		// ļ
#define NR_INODE 32
#define NR_FILE 64
#define NR_SUPER 8
#define NR_HASH 307
#define NR_BUFFERS nr_buffers
#define BLOCK_SIZE 1024		// ݿ鳤ȡ
#define BLOCK_SIZE_BITS 10	// ݿ鳤ռλ
#ifndef NULL
#define NULL ((void *) 0)
#endif

// ÿ߼ɴŵi ڵ
#define INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct d_inode)))
// ÿ߼ɴŵĿ¼
#define DIR_ENTRIES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct dir_entry)))

// ܵͷܵβܵСܵգܵܵͷָ
#define PIPE_HEAD(inode) ((inode).i_zone[0])
#define PIPE_TAIL(inode) ((inode).i_zone[1])
#define PIPE_SIZE(inode) ((PIPE_HEAD(inode)-PIPE_TAIL(inode))&(PAGE_SIZE-1))
#define PIPE_EMPTY(inode) (PIPE_HEAD(inode)==PIPE_TAIL(inode))
#define PIPE_FULL(inode) (PIPE_SIZE(inode)==(PAGE_SIZE-1))
#define INC_PIPE(head) \
__asm__( "incl %0\n\tandl $4095,%0":: "m" (head))

typedef char buffer_block[BLOCK_SIZE];	// 黺

// ͷݽṹΪҪ
// ڳгbh ʾbuffer_head ͵д
struct buffer_head
{
  char *b_data;			/* pointer to data block (1024 bytes) *///ָ롣
  unsigned long b_blocknr;	/* block number */// š
  unsigned short b_dev;		/* device (0 = free) */// Դ豸š
  unsigned char b_uptodate;	// ±־ʾǷѸ¡
  unsigned char b_dirt;		/* 0-clean,1-dirty *///޸ı־:0 δ޸,1 ޸.
  unsigned char b_count;	/* users using this block */// ʹõû
  unsigned char b_lock;		/* 0 - ok, 1 -locked */// Ƿ
  struct task_struct *b_wait;	// ָȴû
  struct buffer_head *b_prev;	// hash ǰһ飨ĸָڻĹ
  struct buffer_head *b_next;	// hash һ顣
  struct buffer_head *b_prev_free;	// бǰһ顣
  struct buffer_head *b_next_free;	// бһ顣
};

// ϵڵ(i ڵ)ݽṹ
struct d_inode
{
  unsigned short i_mode;	// ļͺ(rwx λ)
  unsigned short i_uid;		// ûidļӵ߱ʶ
  unsigned long i_size;		// ļСֽ
  unsigned long i_time;		// ޸ʱ䣨1970.1.1:0 룩
  unsigned char i_gid;		// id(ļӵڵ)
  unsigned char i_nlinks;	// ٸļĿ¼ָi ڵ㣩
  unsigned short i_zone[9];	// ֱ(0-6)(7)˫ؼ(8)߼š
// zone ˼Σ߼顣
};

// ڴеi ڵṹǰ7 d_inode ȫһ
struct m_inode
{
  unsigned short i_mode;	// ļͺ(rwx λ)
  unsigned short i_uid;		// ûidļӵ߱ʶ
  unsigned long i_size;		// ļСֽ
  unsigned long i_mtime;	// ޸ʱ䣨1970.1.1:0 룩
  unsigned char i_gid;		// id(ļӵڵ)
  unsigned char i_nlinks;	// ļĿ¼
  unsigned short i_zone[9];	// ֱ(0-6)(7)˫ؼ(8)߼š
/* these are in memory also */
  struct task_struct *i_wait;	// ȴi ڵĽ̡
  unsigned long i_atime;	// ʱ䡣
  unsigned long i_ctime;	// i ڵ޸ʱ䡣
  unsigned short i_dev;		// i ڵڵ豸š
  unsigned short i_num;		// i ڵš
  unsigned short i_count;	// i ڵ㱻ʹõĴ0 ʾi ڵС
  unsigned char i_lock;		// ־
  unsigned char i_dirt;		// ޸()־
  unsigned char i_pipe;		// ܵ־
  unsigned char i_mount;	// װ־
  unsigned char i_seek;		// Ѱ־(lseek ʱ)
  unsigned char i_update;	// ±־
};

// ļṹļi ڵ֮佨ϵ
struct file
{
  unsigned short f_mode;	// ļģʽRW λ
  unsigned short f_flags;	// ļ򿪺ͿƵı־
  unsigned short f_count;	// Ӧļļ
  struct m_inode *f_inode;	// ָӦi ڵ㡣
  off_t f_pos;			// ļλãдƫֵ
};

// ڴд̳ṹ
struct super_block
{
  unsigned short s_ninodes;	// ڵ
  unsigned short s_nzones;	// ߼
  unsigned short s_imap_blocks;	// i ڵλͼռõݿ
  unsigned short s_zmap_blocks;	// ߼λͼռõݿ
  unsigned short s_firstdatazone;	// һ߼š
  unsigned short s_log_zone_size;	// log(ݿ/߼)2 Ϊף
  unsigned long s_max_size;	// ļ󳤶ȡ
  unsigned short s_magic;	// ļϵͳħ
/* These are only in memory */
  struct buffer_head *s_imap[8];	// i ڵλͼָ(ռ8 飬ɱʾ64M)
  struct buffer_head *s_zmap[8];	// ߼λͼָ飨ռ8 飩
  unsigned short s_dev;		// ڵ豸š
  struct m_inode *s_isup;	// װļϵͳĿ¼i ڵ㡣(isup-super i)
  struct m_inode *s_imount;	// װi ڵ㡣
  unsigned long s_time;		// ޸ʱ䡣
  struct task_struct *s_wait;	// ȴóĽ̡
  unsigned char s_lock;		// ־
  unsigned char s_rd_only;	// ֻ־
  unsigned char s_dirt;		// ޸()־
};

// ϳṹ125-132 ȫһ
struct d_super_block
{
  unsigned short s_ninodes;	// ڵ
  unsigned short s_nzones;	// ߼
  unsigned short s_imap_blocks;	// i ڵλͼռõݿ
  unsigned short s_zmap_blocks;	// ߼λͼռõݿ
  unsigned short s_firstdatazone;	// һ߼顣
  unsigned short s_log_zone_size;	// log(ݿ/߼)2 Ϊף
  unsigned long s_max_size;	// ļ󳤶ȡ
  unsigned short s_magic;	// ļϵͳħ
};

// ļĿ¼ṹ
struct dir_entry
{
  unsigned short inode;		// i ڵ㡣
  char name[NAME_LEN];		// ļ
};

extern struct m_inode inode_table[NR_INODE];	// i ڵ飨32 
extern struct file file_table[NR_FILE];	// ļ飨64 
extern struct super_block super_block[NR_SUPER];	// 飨8 
extern struct buffer_head *start_buffer;	// ʼڴλá
extern int nr_buffers;		// 

//// ̲ԭ͡
// Ƿı䡣
extern void check_disk_change (int dev);
// ̸̸ָ򷵻1򷵻0
extern int floppy_change (unsigned int nr);
// ָȴʱ䣨õȴʱ
extern int ticks_to_floppy_on (unsigned int dev);
// ָ
extern void floppy_on (unsigned int dev);
// رָ
extern void floppy_off (unsigned int dev);
//// ļϵͳõĺԭ͡
// i ڵָļΪ0
extern void truncate (struct m_inode *inode);
// ˢi ڵϢ
extern void sync_inodes (void);
// ȴָi ڵ㡣
extern void wait_on (struct m_inode *inode);
// ߼(Σ̿)λͼȡݿblock 豸϶Ӧ߼š
extern int bmap (struct m_inode *inode, int block);
// ݿblock 豸϶Ӧ߼飬豸ϵ߼š
extern int create_block (struct m_inode *inode, int block);
// ȡָ·i ڵš
extern struct m_inode *namei (const char *pathname);
// ·Ϊļ׼
extern int open_namei (const char *pathname, int flag, int mode,
		       struct m_inode **res_inode);
// ͷһi ڵ(д豸)
extern void iput (struct m_inode *inode);
// 豸ȡָڵŵһi ڵ㡣
extern struct m_inode *iget (int dev, int nr);
// i ڵ(inode_table)лȡһi ڵ
extern struct m_inode *get_empty_inode (void);
// ȡһܵڵ㡣Ϊi ڵָ루NULL ʧܣ
extern struct m_inode *get_pipe_inode (void);
// ڹϣвָݿ顣ҵĻͷָ롣
extern struct buffer_head *get_hash_table (int dev, int block);
// 豸ȡָ飨Ȼhash вң
extern struct buffer_head *getblk (int dev, int block);
// /дݿ顣
extern void ll_rw_block (int rw, struct buffer_head *bh);
// ͷָ顣
extern void brelse (struct buffer_head *buf);
// ȡָݿ顣
extern struct buffer_head *bread (int dev, int block);
// 4 黺ַָڴС
extern void bread_page (unsigned long addr, int dev, int b[4]);
// ȡͷһָݿ飬ǺҪĿ顣
extern struct buffer_head *breada (int dev, int block, ...);
// 豸dev һ̿飨Σ߼飩߼
extern int new_block (int dev);
// ͷ豸е߼(Σ̿)blockλָ߼block ߼λͼλ
extern void free_block (int dev, int block);
// Ϊ豸dev һi ڵ㣬i ڵš
extern struct m_inode *new_inode (int dev);
// ͷһi ڵ㣨ɾļʱ
extern void free_inode (struct m_inode *inode);
// ˢָ豸
extern int sync_dev (int dev);
// ȡָ豸ĳ顣
extern struct super_block *get_super (int dev);
extern int ROOT_DEV;

// װļϵͳ
extern void mount_root (void);

#endif
