tty_alloc_driver

  /inclue/linux/tty_driver.h

/* Use TTY_DRIVER_* flags below */

#define tty_alloc_driver(lines, flags) \

                __tty_alloc_driver(lines, THIS_MODULE, flags)

/*

 * DEPRECATED Do not use this in new code, use tty_alloc_driver instead.

 * 不赞成使用这个新代码,通常使用tty_alloc_driver来代替。其实他们实际意义是一样的

 * (And change the return value checks.)

 */

static inline struct tty_driver *alloc_tty_driver(unsigned int lines)

{

    struct tty_driver *ret = tty_alloc_driver(lines, 0);

//当看到代码中调用alloc_tty_driver时,flag默认为0

    if (IS_ERR(ret))

        return NULL;

    return ret;

}

----------------------------------------------------------------------

/*

 * tty driver flags

 *   

 * TTY_DRIVER_RESET_TERMIOS --- requests the tty layer to reset the

 *      termios setting when the last process has closed the device.

 *      Used for PTY's, in particular.

 * 当设备关闭时,请求复位termios。通常使用PTY

 * 

 * TTY_DRIVER_REAL_RAW --- if set, indicates that the driver will

 *      guarantee never not to set any special character handling

 *      flags if ((IGNBRK || (!BRKINT && !PARMRK)) && (IGNPAR ||

 *      !INPCK)).  That is, if there is no reason for the driver to

 *      send notifications of parity and break characters up to the

 *      line driver, it won't do so.  This allows the line driver to

 *      optimize for this case if this flag is set.  (Note that there

 *      is also a promise, if the above case is true, not to signal

 *      overruns, either.)

 * 如果设置,驱动将不会设置任何特殊的字符处理标志 

 * 意味着,如果没有原因,驱动将不会将通知送给线驱动

 * 如果设置了,可以使线驱动优化这一处理程序

 *

 * TTY_DRIVER_DYNAMIC_DEV --- if set, the individual tty devices need

 *      to be registered with a call to tty_register_device() when the

 *      device is found in the system and unregistered with a call to

 *      tty_unregister_device() so the devices will be show up

 *      properly in sysfs.  If not set, driver->num entries will be

 *      created by the tty core in sysfs when tty_register_driver() is

 *      called.  This is to be used by drivers that have tty devices

 *      that can appear and disappear while the main tty driver is

 *      registered with the tty core.

 * 如果设置,特别的tty设备将在其被发现时注册 和 调用注销函数时注销

 * 如果不设置,当注册函数被调用时,sysfs的tty核心层会自动创建driver->num

 * 这个flag通常使用在主tty驱动被tty核心注册,且tty设备可能出现和消失

 * 

 * TTY_DRIVER_DEVPTS_MEM -- don't use the standard arrays, instead

 *      use dynamic memory keyed through the devpts filesystem.  This

 *      is only applicable to the pty driver.

 * 不使用标准数组, 而是使用devpts文件系统的动态记忆链

 * 这个是给pty驱动使用的

 *

 * TTY_DRIVER_HARDWARE_BREAK -- hardware handles break signals. Pass

 *      the requested timeout to the caller instead of using a simple

 *      on/off interface.

 * 硬件处理断点信号。发送暂时休息(timeout)请求而不是简单地打开/关闭接口

 *

 * TTY_DRIVER_DYNAMIC_ALLOC -- do not allocate structures which are

 *      needed per line for this driver as it would waste memory.

 *      The driver will take care.

 * 不每条线都分配结构,因其会浪费内存。使用这个flag,驱动将注意这一情况

 *

 * TTY_DRIVER_UNNUMBERED_NODE -- do not create numbered /dev nodes. In

 *      other words create /dev/ttyprintk and not /dev/ttyprintk0.

 *      Applicable only when a driver for a single tty device is

 *      being allocated.

 * 不创建已经分配的/dev节点。

 * 意思是创建/dev/ttyprintk 而非创建/dev/ttyprintk0

 * 只用在一个驱动为了一个单独的且已经被分配tty设备注册时

 */

#define TTY_DRIVER_INSTALLED            0x0001

#define TTY_DRIVER_RESET_TERMIOS        0x0002

#define TTY_DRIVER_REAL_RAW             0x0004

#define TTY_DRIVER_DYNAMIC_DEV          0x0008

#define TTY_DRIVER_DEVPTS_MEM           0x0010

#define TTY_DRIVER_HARDWARE_BREAK       0x0020

#define TTY_DRIVER_DYNAMIC_ALLOC        0x0040

#define TTY_DRIVER_UNNUMBERED_NODE      0x0080

  在看分配函数之前,先来看一下tty_driver这个结构体

  /include/linux/tty/tty_driver.h

struct tty_driver {

    int     magic;          /* magic number for this structure */

    struct kref kref;       /* Reference management */

    struct cdev *cdevs;

    struct module   *owner;

    const char      *driver_name;

    const char      *name;

    int     name_base;      /* offset of printed name */

    int     major;          /* major device number */

    int     minor_start;    /* start of minor device number */

    unsigned int    num;    /* number of devices allocated */

    short   type;           /* type of tty driver */

    short   subtype;        /* subtype of tty driver */

    struct ktermios init_termios; /* Initial termios */

    unsigned long   flags;          /* tty driver flags */

    struct proc_dir_entry *proc_entry; /* /proc fs entry */

    struct tty_driver *other; /* only used for the PTY driver */



    /*

     * Pointer to the tty data structures

     */

    struct tty_struct **ttys;

    struct tty_port **ports;

    struct ktermios **termios;

    void *driver_state;



    /*

     * Driver methods

     */



    const struct tty_operations *ops;

    struct list_head tty_drivers;

};

   分配tty驱动函数

  /drivers/tty/tty_io.c

/**

 * __tty_alloc_driver -- allocate tty driver

 * @lines: count of lines this driver can handle at most

 * @owner: module which is repsonsible for this driver

 * @flags: some of TTY_DRIVER_* flags, will be set in driver->flags

 *

 * This should not be called directly, some of the provided macros should be

 * used instead. Use IS_ERR and friends on @retval.

 */

struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner,

        unsigned long flags)

{

    struct tty_driver *driver;

    unsigned int cdevs = 1;

    int err;



    if (!lines || (flags & TTY_DRIVER_UNNUMBERED_NODE && lines > 1))

//The priority is '&' higher than '&&'

//当设置flag为TTY_DRIVER_UNNUMBERD_NODE或lines为0的时候,返回-EINVAL

//means -E(rror)IN(put)VAL(ue)

        return ERR_PTR(-EINVAL);



    driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL);

    if (!driver)  //若分配失败,返回-ENOMEM

        return ERR_PTR(-ENOMEM);



    kref_init(&driver->kref);

    driver->magic = TTY_DRIVER_MAGIC;

    driver->num = lines;

    driver->owner = owner;

    driver->flags = flags;



//看看声明的flags有什么特点就知道这个 & 的作用了

    if (!(flags & TTY_DRIVER_DEVPTS_MEM)) {

//若没设置TTY_DRIVER_DEVPTS_MEM

//使用标准数组

        driver->ttys = kcalloc(lines, sizeof(*driver->ttys),

                GFP_KERNEL);

//定义为struct tty_struct **tty, kcalloc分配成功返回0

        driver->termios = kcalloc(lines, sizeof(*driver->termios),

                GFP_KERNEL);

//定义为struct ktermios **termios

        if (!driver->ttys || !driver->termios) {

//ttys和termios任一成功才继续往下

            err = -ENOMEM;

            goto err_free_all;

        }

    }



    if (!(flags & TTY_DRIVER_DYNAMIC_ALLOC)) {

//若没设置TTY_DRIVER_DYNAMIC_ALLOC, 则为每条线都分配结构

        driver->ports = kcalloc(lines, sizeof(*driver->ports),

                GFP_KERNEL);

        if (!driver->ports) {

            err = -ENOMEM;

            goto err_free_all;

        }

        cdevs = lines;

    }



    driver->cdevs = kcalloc(cdevs, sizeof(*driver->cdevs), GFP_KERNEL);

    if (!driver->cdevs) {

        err = -ENOMEM;

        goto err_free_all;

    }



    return driver;

err_free_all:

    kfree(driver->ports);

    kfree(driver->ttys);

    kfree(driver->termios);

    kfree(driver);

    return ERR_PTR(err);

}

EXPORT_SYMBOL(__tty_alloc_driver);

 

 

 
  

 

你可能感兴趣的:(driver)