/*
* linux/fs/ioctl.c
*
* (C) 1991 Linus Torvalds
*/

#include <string.h>		// ַͷļҪһЩйַǶ뺯
#include <errno.h>		// ͷļϵͳиֳš(Linus minix )
#include <sys/stat.h>		// ļ״̬ͷļļļϵͳ״̬ṹstat{}ͳ

#include <linux/sched.h>	// ȳͷļṹtask_structʼ0 ݣ
// һЩйúͻȡǶʽຯ䡣

extern int tty_ioctl (int dev, int cmd, int arg);	// նioctl(chr_drv/tty_ioctl.c, 115)

// (ioctl)ָ롣
typedef int (*ioctl_ptr) (int dev, int cmd, int arg);

// ϵͳ豸
#define NRDEVS ((sizeof (ioctl_table))/(sizeof (ioctl_ptr)))

// ioctl ָ
static ioctl_ptr ioctl_table[] = {
  NULL,				/* nodev */
  NULL,				/* /dev/mem */
  NULL,				/* /dev/fd */
  NULL,				/* /dev/hd */
  tty_ioctl,			/* /dev/ttyx */
  tty_ioctl,			/* /dev/tty */
  NULL,				/* /dev/lp */
  NULL
};				/* named pipes */


//// ϵͳú - ƺ
// fd - ļcmd - 룻arg - 
// أɹ򷵻0򷵻س롣
int
sys_ioctl (unsigned int fd, unsigned int cmd, unsigned long arg)
{
  struct file *filp;
  int dev, mode;

// ļɴ򿪵ļ߶ӦļṹָΪգ򷵻س룬˳
  if (fd >= NR_OPEN || !(filp = current->filp[fd]))
    return -EBADF;
// ȡӦļԡļַļҲǿ豸ļ򷵻س룬˳
  mode = filp->f_inode->i_mode;
  if (!S_ISCHR (mode) && !S_ISBLK (mode))
    return -EINVAL;
// ַ豸ļi ڵȡ豸š豸Ŵϵͳе豸򷵻سš
  dev = filp->f_inode->i_zone[0];
  if (MAJOR (dev) >= NRDEVS)
    return -ENODEV;
// 豸ioctl ָûжӦ򷵻س롣
  if (!ioctl_table[MAJOR (dev)])
    return -ENOTTY;
// 򷵻ʵioctl 룬ɹ򷵻0򷵻س롣
  return ioctl_table[MAJOR (dev)] (dev, cmd, arg);
}
